wyrd-1.4.4/0000755000175000017500000000000010757447267011214 5ustar paulpaulwyrd-1.4.4/locale.ml0000644000175000017500000000310610757447265013003 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* OCaml binding for setlocale(), required to kick ncurses into * properly rendering non-ASCII chars. *) type t = LC_ALL | LC_COLLATE | LC_CTYPE | LC_MONETARY | LC_NUMERIC | LC_TIME | LC_MESSAGES | LC_UNDEFINED of int (* Binds to C library setlocale() *) external setlocale_int : int -> string -> string = "ml_setlocale" (* Provide a more OCamlish interface *) let setlocale (category : t) (param : string) = let int_category = match category with | LC_ALL -> 0 | LC_COLLATE -> 1 | LC_CTYPE -> 2 | LC_MONETARY -> 3 | LC_NUMERIC -> 4 | LC_TIME -> 5 | LC_MESSAGES -> 6 | LC_UNDEFINED i -> i in setlocale_int int_category param wyrd-1.4.4/COPYING0000644000175000017500000004312710757447264012253 0ustar paulpaul GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 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. Copyright (C) 19yy 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. , 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. wyrd-1.4.4/doc/0000755000175000017500000000000010757447275011760 5ustar paulpaulwyrd-1.4.4/doc/manual.html0000644000175000017500000013423610757447275014134 0ustar paulpaul Wyrd v1.4 User Manual

Wyrd v1.4 User Manual

Paul J. Pelzl

August 17, 2007

“Because you’re tired of waiting for your bloated calendar program to start up.”

Contents

1  Introduction

Wyrd is a text-based front-end to Remind, a sophisticated calendar and alarm program available from Roaring Penguin Software, Inc. Wyrd serves two purposes:

  1. It displays reminders in a scrollable timetable view suitable for visualizing your calendar at a glance.
  2. It makes creating and editing reminders fast and easy. However, Wyrd does not hide Remind’s textfile programmability, for this is what makes Remind a truly powerful calendaring system.

Wyrd also requires only a fraction of the resources of most calendar programs available today.

2  Installation

This section describes how to install Wyrd by compiling from source. Volunteers have pre-packaged Wyrd for several popular operating systems, so you may be able to save yourself some time by installing from those packages. Please check the Wyrd website for up-to-date package information.

Wyrd is designed to be portable to most Unix-like operating systems, including GNU/Linux, *BSD, and Mac OS X. Before installing Wyrd, your system must have the following software installed:

Wyrd may be compiled by executing the following at the root of the source tree:

./configure
make

After compiling, become root and execute

make install

to complete the installation process. The make command here should correspond to GNU make; on some systems (particularly *BSD), you may need to use gmake.

If your ncurses library was built with wide character support, Wyrd can be configured to render UTF-8 encoded reminders. To enable this option, use the command

./configure --enable-utf8

when configuring the sources.

3  Quick Start

This section describes how to use Wyrd in its default configuration. After familiarizing yourself with the basic operations as outlined in this section, you may wish to consult Section 4 to see how Wyrd can be configured to better fit your needs.

3.1  Overview

Before attemping to use Wyrd, learn how to use Remind. Wyrd makes no attempt to hide the details of Remind programming from the user. Aside from reading the Remind manpage, you may get some useful pointers by reading Mike Harris's article on 43 folders or David Skoll's writeup on Linux Journal. The 43 Folders Wiki also has a nice section on Remind.

You can launch Wyrd using the default reminder file by executing wyrd. If desired, a different reminder file may be selected by executing wyrd <filename>.

At the top of the window is a short (incomplete) list of keybindings.

The left window displays a scrollable timetable view, with reminders highlighted in various colors. If the DURATION specifier is used for a reminder, the highlighted area is rendered with an appropriate size. Overlapping reminders are rendered using one of four different indentation levels so that all reminders are at least partially visible. If the current time is visible in this window, it is highlighted in red.

The upper right window displays a month calendar, with the color of each day representing the number of reminders it contains. The colors range across shades of white to blue to magenta as the number of reminders increases. The selected date is highlighted in cyan; if the current date is visible, it is highlighted in red.

The lower right window displays a list of the untimed reminders falling on the selected date.

The bottom window displays the full text of the MSG for the reminder or reminders that are currently selected.

3.2  Navigation

ActionKeypress
scroll up and down the schedule<up>, <down> or k, j
jump back or forward by a day<pageup>, <pagedown> or 4, 6 or <, > or H, L
jump back or forward by a week8, 2 or [, ] or K, J
jump back or forward by a month{, }
jump to current date and time<home>
jump to the next reminder<tab>
switch between schedule and untimed reminders window<left>, <right> or h, l
zoom in on the schedulez
scroll the description window up and downd, D

Notice that if you have a numeric keypad, the {4, 6, 8, 2} keys will let you move directionally in the month calendar view at the upper-right of the screen. Similarly, {H, J, K, L} will cause directional calendar movement using the standard mapping from vi(1).

In addition to the hotkeys provided above, Wyrd lets you jump immediately to a desired date by pressing ’g’, entering in a date specifier, and then pressing <return>. Any of the following date specifiers may be used:

  • 8 digits representing year, month, and day: YYYYMMDD
  • 4 digits representing month and day (of current year): MMDD
  • 2 digits representing day (of current month and year): DD

(The date specifier format may be changed to DDMMYYYY; consult Section 4.2. )

3.3  Editing Reminders

Note: By default, Wyrd is configured to modify your reminder files using the text editor specified by the $EDITOR environment variable. (This configuration has been tested successfully with a number of common settings for $EDITOR, including ’vim’, ’emacs’, and ’nano’.) If you wish to use a different editor, see Section 4.

If you select a timeslot in the schedule view, then hit ’t’, you will begin creating a new timed reminder. Wyrd will open up your reminder file in your favorite editor and move the cursor to the end of the file, where a new reminder template has been created. The template has the selected date and time filled in, so in many cases you will only need to fill in a MSG value.

Similarly, hitting ’u’ will begin creating an untimed reminder. ’w’ will create a weekly timed reminder, and ’W’ will create a weekly untimed reminder; ’m’ will create a monthly timed reminder, and ’M’ will create a monthly untimed reminder.

’T’ and ’U’ also create timed and untimed reminders (respectively), but first will provide a selection dialog for you to choose which reminder file you want to add this reminder to. The set of reminder files is determined by scanning the INCLUDE lines in your default reminder file.

If you select a reminder (either timed or untimed) and hit <return>, you will begin editing that reminder. Wyrd will open up the appropriate reminders file in your editor and move the cursor to the corresponding REM line.

If you select a timeslot that contains multiple overlapping reminders, Wyrd will provide a dialog that allows you to select the desired reminder.

If you hit <enter> on a blank timeslot, Wyrd will begin creating a new timed or untimed reminder (depending on whether the timed or the untimed window is selected).

Finally, pressing ’e’ will open the reminder file in your editor without attempting to select any particular reminder.

3.4  Quick Reminders

Wyrd offers an additional mode for entering simple reminders quickly. Press ’q’, and you will be prompted for an event description. Simply enter a description for the event using natural language, then press <return>. Examples:

  • meeting with Bob tomorrow at 11
  • drop off package at 3pm
  • wednesday 10am-11:30 go grocery shopping
  • Board game night 20:15 next Fri
  • 7/4 independence day
  • 7/4/2007 independence day (next year)
  • independence day (next year) on 2007-07-04

If your event description can be understood, Wyrd will immediately create the reminder and scroll the display to its location.

Currently the quick reminder mode tends to favor USA English conventions, as generalizing the natural language parser would require some work.

Wyrd also allows you to use the "quick reminder" syntax to create new reminders from the command line, using the -a or --add options. For example,

wyrd --add "dinner with neighbors tomorrow at 7pm"

would create a new reminder for tomorrow evening. When used in this mode, Wyrd exits silently with error code 0 if the reminder was successfully created. If the reminder could not be created (e.g. if the reminder syntax could not be parsed), Wyrd prints an error message and exits with a nonzero error code.

3.5  Cutting and Pasting Reminders

Reminders can be easily duplicated or rescheduled through the use of Wyrd’s cutting and pasting features.

Selecting a reminder and pressing ’X’ will cut that reminder: the corrdsponding REM line is deleted from your reminders file, and the reminder is copied to Wyrd’s clipboard. To copy a reminder without deleting it, use ’y’ instead.

To paste a reminder from the clipboard back into your schedule, just move the cursor to the desired date/time and press ’p’. Wyrd will append a new REM line to the end of your reminders file, and open the file with your editor. The REM line will be configured to trigger on the selected date. If the copied reminder was timed, then the pasted reminder will be set to trigger at the selected time using the original DURATION setting. (Additional Remind settings such as delta and tdelta are not preserved by copy-and-paste.)

If you wish to paste a reminder into a non-default reminders file, use ’P’. This will spawn a selection dialog where you can choose the file that will hold the new reminder.

WARNING: Cutting a reminder will delete only the single REM command responsible for triggering it. If you are using more complicated Remind scripting techniques to generate a particular reminder, then the cut operation may not do what you want.

3.6  Viewing Reminders

Aside from viewing reminders as they fall in the schedule, you can press ’r’ to view all reminders triggered on the selected date in a less(1) window. Similarly, ’R’ will view all reminders triggered on or after the selected date (all non-expired reminders are triggered).

If you want to get a more global view of your schedule, Wyrd will also let you view Remind’s formatted calendar output in a less(1) window. Pressing ’c’ will view a one-week calendar that contains the selected date, while pressing ’C’ will view a one-month calendar containing the selected date.

3.7  Searching for Reminders

Wyrd allows you to search for reminders with MSG values that match a search string. Press ’/’ to start entering a (case insensitive) regular expression. After the expression has been entered, press <return> and Wyrd will locate the next reminder that matches the regexp. Press ’n’ to repeat the same search. Entry of a search string may be cancelled with <esc>.

The regular expression syntax is Emacs-compatible.

Note: Sorry, there is no "search backward" function. The search function requires the use of "remind -n", which operates only forward in time. For the same reason, there is a command to jump forward to the next reminder, but no command to jump backward to the previous reminder.

3.8  Other Commands

A list of all keybindings may be viewed by pressing ’?’. You can exit Wyrd by pressing ’Q’. If the screen is corrupted for some reason, hit ’Ctrl-L’ to refresh the display.

3.9  Alarm Strategies

You may wish to generate some sort of alarm when a reminder is triggered. Wyrd does not offer any special alarm functionality, because Remind can handle the job already. Check the Remind manpage and consider how the -k option could be used to generate alarms with the aid of external programs. For example, the following command will generate a popup window using gxmessage(1) whenever a timed reminder is triggered:

remind -z -k'gxmessage -title "reminder" %s &' ~/.reminders &

(A sensible way to start this alarm command is to place it in ~.xinitrc so that it launches when the X server is started.) If you want some advance warning (say, 15 minutes), you can cause Remind to trigger early by setting a tdelta in the AT clause:

   REM Nov 27 2005 AT 14:30 +15 MSG Do something

Alternatively, if you want to generate alarms only for specific reminders, consider using Remind’s RUN command. This process could be easily automated by using the templateN configuration variables described in Section 4.

3.10  Miscellaneous

Remind’s TAG specifier may be used to cause Wyrd to give special treatment to certain reminders. If a reminder line includes the clause "TAG noweight", then Wyrd will not give that reminder any weight when determining the “busy level” colorations applied to the month calendar. If a reminder line includes the clause "TAG nodisplay", then Wyrd will neither display that reminder nor give it any weight when determining the month calendar colorations. The tag parameters are case insensitive.

WARNING: These tag parameters are not guaranteed to interact well with other Remind front-ends such as tkremind.

4  Advanced Configuration

Wyrd reads a run-configuration textfile (generally /etc/wyrdrc or /usr/local/etc/wyrdrc) to determine key bindings, color schemes, and many other settings. You can create a personalized configuration file in $HOME/.wyrdrc, and select settings that match your usage patterns. The recommended procedure is to “include” the wyrdrc file provided with Wyrd (see Section 4.1.1), and add or remove settings as desired.

4.1  wyrdrc Syntax

You may notice that the wyrdrc syntax is similar to the syntax used in the configuration file for the Mutt email client (muttrc).

Within the wyrdrc file, strings should be enclosed in double quotes ("). A double quote character inside a string may be represented by \" . The backslash character must be represented by doubling it (\\).

4.1.1  Including Other Rcfiles

Syntax: include filename_string

This syntax can be used to include one run-configuration file within another. This command could be used to load the default wyrdrc file (probably found in /etc/wyrdrc or /usr/local/etc/wyrdrc) within your personalized rcfile, ~/.wyrdrc. The filename string should be enclosed in quotes.

4.1.2  Setting Configuration Variables

Syntax: set variable=value_string

A number of configuration variables can be set using this syntax; check Section 4.2 to see a list. The variables are unquoted, but the values should be quoted strings.

4.1.3  Creating Key Bindings

Syntax: bind key_identifier operation

This command will bind a keypress to execute a calendar operation. The various operations, which should not be enclosed in quotes, may be found in Section 4.3. Key identifiers may be specified by strings that represent a single keypress, for example "m" (quotes included). The key may be prefixed with "\\C" or "\\M" to represent Control or Meta (Alt) modifiers, respectively; note that the backslash must be doubled. A number of special keys lack single-character representations, so the following strings may be used to represent them:

  • "<esc>"
  • "<tab>"
  • "<enter>"
  • "<return>"
  • "<insert>"
  • "<home>"
  • "<end>"
  • "<pageup>"
  • "<pagedown>"
  • "<space>"
  • "<left>"
  • "<right>"
  • "<up>"
  • "<down>"
  • "<f1>" to "<f12>"

Due to differences between various terminal emulators, this key identifier syntax may not be adequate to describe every keypress. As a workaround, Wyrd will also accept key identifiers in octal notation. As an example, you could use \024 (do not enclose it in quotes) to represent Ctrl-T.

Multiple keys may be bound to the same operation, if desired.

4.1.4  Removing Key Bindings

Syntax: unbind key_identifier

This command will remove all bindings associated with the key identifier. The key identifiers should be defined using the syntax described in the previous section.

4.1.5  Setting the Color Scheme

Syntax: color object foreground background

This command will apply the specified foreground and background colors to the appropriate object. A list of colorable objects is provided in Section 4.4. Wyrd will recognize the following color keywords: black, red, green, yellow, blue, magenta, cyan, white, default. The default keyword allows you to choose the default foreground or background colors. If you use default for your background color, this will access the transparent background on terminal emulators which support it.

4.2  Configuration Variables

The following configuration variables may be set as described in Section 4.1.2:

  • remind_command
    Determines the command used to execute Remind.
  • reminders_file
    Controls which Remind file Wyrd will operate on. The default is ~/.reminders .
  • edit_old_command
    Controls the command used to edit a pre-existing reminder. The special strings ’%file%’ and ’%line%’ will be replaced with a filename to edit and a line number to navigate to within that file.
  • edit_new_command
    Controls the command used to edit a new reminder. The special character ’%file%’ will be replaced with a filename to edit. Ideally, this command should move the cursor to the last line of the file, where the new reminder template is created.
  • edit_any_command
    Controls the command used for editing a reminder file without selecting any particular reminder. The special character ’%file%’ will be replaced with a filename to edit.
  • timed_template
    Controls the format of the REM line created when editing a new timed reminder. The following string substitutions will be made: ’%monname%’ - month name, ’%mon%’ - month number, ’%mday%’ - day of the month, ’%year%’ - year, ’%hour%’ - hour, ’%min%’ - minute, ’%wdayname%’ - weekday name, ’%wday%’ - weekday number.
  • untimed_template
    Controls the format of the REM line created when editing a new untimed reminder. The substitution syntax is the same as for timed_template.
  • templateN
    Controls the format of a generic user-defined REM line template; N may range from 0 to 9. The substitution syntax is the same as for timed_template.
  • busy_algorithm
    An integer value specifying which algorithm to use for measuring how busy the user is on a particular day. If busy_algorithm="1", then Wyrd will simply count the total number of reminders triggered on that day. If busy_algorithm="2", then Wyrd will count the number of hours of reminders that fall on that day. (Untimed reminders are assumed to occupy untimed_duration minutes.)
  • untimed_duration
    An integer value that specifies the assumed duration of an untimed reminder, in minutes. This is used only when computing the busy level with busy_algorithm="2".
  • busy_level1
    An integer value specifying the maximum number of reminders in a day (with busy_algorithm="1") or maximum hours of reminders in a day (with busy_algorithm="2") which will be colored using the color scheme for calendar_level1.
  • busy_level2
    Same as above, using the calendar_level2 color scheme.
  • busy_level3
    Same as above, using the calendar_level2 color scheme rendered in bold.
  • busy_level4
    Same as above, using the calendar_level3 color scheme. Any day with more reminders than this will be rendered using the calendar_level3 color scheme rendered in bold.
  • week_starts_monday
    A boolean value ("true" or "false") that determines the first day of the week.
  • schedule_12_hour
    A boolean value that determines whether the timed reminders window is drawn using 12- or 24-hour time.
  • selection_12_hour
    A boolean value that determines whether the selection information is drawn with 12- or 24-hour time.
  • status_12_hour
    A boolean value that determines whether the current time is drawn using a 12- or 24-hour clock.
  • description_12_hour
    A boolean value that determines whether reminder start and end times are drawn using 12- or 24-hour time in the description window. This value also controls the format of timestamps in the formatted calendars produced by view_week and view_month.
  • center_cursor
    A boolean value that determines how the screen and cursor move during scrolling operations. When set to "true", the cursor is fixed in the center of the timed reminders window, and the schedule scrolls around it. When set to "false" (the default), the cursor will move up and down the schedule during scrolling operations.
  • goto_big_endian
    A boolean value that determines how the the goto operation will parse dates. When set to "true", date specifiers should be in ISO 8601 (YYYYMMDD) format. When set to "false", date specifiers should be in European style DDMMYYYY format.
  • quick_date_US
    A boolean value that determines how the quick_add operation will parse numeric dates with slashes, e.g. 6/1 (or 6/1/2006). When set to "true", the first number is a month and the second is the day of the month (June 1). When set to "false", these meanings of these two fields are switched (January 6).
  • number_weeks
    A boolean value that determines whether or not weeks should be numbered within the month calendar window. Weeks are numbered according to the ISO 8601 standard. The ISO standard week begins on Monday, so to avoid confusion it is recommended that week_starts_monday be set to "true" when week numbering is enabled.
  • home_sticky
    A boolean value that determines whether or not the cursor should "stick" to the "home" position. When this option is set to "true", then after pressing the <home> key the cursor will automatically follow the current date and time. The effect is cancelled by pressing any of the navigation keys.
  • untimed_window_width
    An integer value that determines the target width of the month-calendar window and the untimed reminders window. The allowable range is 34 to ($COLUMNS - 40) characters, and Wyrd will silently disregard any setting outside this range.
  • advance_warning
    A boolean value that determines whether or not Wyrd should display advance warning of reminders. When set to "true", Wyrd will invoke Remind in a mode that generates advance warning of reminders as specified in the reminder file.
  • untimed_bold
    A boolean value that determines whether or not Wyrd should render untimed reminders using a bold font.

For maximum usefulness, busy_level1 < busy_level2 < busy_level3 < busy_level4.

4.3  Calendar Operations

Every Wyrd operation can be made available to the interface using the syntax described in Section 4.1.3. The following is a list of every available operation.

  • scroll_up
    move the cursor up one element
  • scroll_down
    move the cursor down one element
  • next_day
    jump ahead one day
  • previous_day
    jump backward one day
  • next_week
    jump ahead one week
  • previous_week
    jump backward one week
  • next_month
    jump ahead one month
  • previous_month
    jump backward one month
  • home
    jump to the current date and time
  • goto
    begin entering a date specifier to jump to
  • zoom
    zoom in on the day schedule view (this operation is cyclic)
  • edit
    edit the selected reminder
  • edit_any
    edit a reminder file, without selecting any particular reminder
  • scroll_description_up
    scroll the description window contents up (when possible)
  • scroll_description_down
    scroll the description window contents down (when possible)
  • quick_add
    add a “quick reminder”
  • new_timed
    create a new timed reminder
  • new_timed_dialog
    same as previous, with a reminder file selection dialog
  • new_untimed
    create a new untimed reminder
  • new_untimed_dialog
    same as previous, with a reminder file selection dialog
  • new_templateN
    create a new user-defined reminder using templateN, where N may range from 0 to 9
  • new_templateN_dialog
    same as previous, with a reminder file selection dialog
  • copy
    copy a reminder to Wyrd’s clipboard
  • cut
    delete a reminder and copy it to Wyrd’s clipboard
  • paste
    paste a reminder from Wyrd’s clipboard into the schedule
  • paste_dialog
    same as previous, with a reminder file selection dialog
  • switch_window
    switch between the day schedule window on the left, and the untimed reminder window on the right
  • begin_search
    begin entering a search string
  • search_next
    search for the next occurrence of the search string
  • next_reminder
    jump to the next reminder1
  • view_remind
    view the output of remind for the selected date
  • view_remind_all
    view the output of remind for the selected date, triggering all non-expired reminders
  • view_week
    view Remind’s formatted calendar for the week that contains the selected date (the in-calendar timestamp formats are determined by the value of description_12_hour)
  • view_month
    view Remind’s formatted calendar for the month that contains the selected date (the in-calendar timestamp formats are determined by the value of description_12_hour)
  • refresh
    refresh the display
  • quit
    exit Wyrd
  • entry_complete
    signal completion of search string entry or date specifier
  • entry_backspace
    delete the last character of the search string or date specifier
  • entry_cancel
    cancel entry of a search string or date specifier

4.4  Colorable Objects

Each of Wyrd’s on-screen elements may be colored by the color scheme of your choice, using the syntax defined in Section 4.1.5. The following is a list of all colorable objects.

  • help
    the help bar at the top of the screen
  • timed_default
    an empty timeslot in the day-schedule window
  • timed_current
    the current time in the day-schedule window (if it is visible)
  • timed_reminder1
    a nonempty timeslot in the day-schedule window, indented to level 1
  • timed_reminder2
    a nonempty timeslot in the day-schedule window, indented to level 2
  • timed_reminder3
    a nonempty timeslot in the day-schedule window, indented to level 3
  • timed_reminder4
    a nonempty timeslot in the day-schedule window, indented to level 4
  • untimed_reminder
    an entry in the untimed reminders window
  • timed_date
    the vertical date strip at the left side of the screen
  • selection_info
    the line providing date/time for the current selection
  • description
    the reminder description window
  • status
    the bottom bar providing current date and time
  • calendar_labels
    the month and weekday labels in the calendar window
  • calendar_level1
    calendar days with low activity
  • calendar_level2
    calendar days with medium activity
  • calendar_level3
    calendar days with high activity
  • calendar_today
    the current day in the calendar window (if it is visible)
  • left_divider
    the vertical line to the left of the timed reminders window
  • right_divider
    the vertical and horizontal lines to the right of the timed reminders window

5  Usage Tips

  • Wyrd fills in sensible defaults for the fields of a REM statement, but you will inevitably need to make some small edits to achieve the behavior you want. If you use Vim, you can make your life easier by installing the Vim-Latex Suite and then modifying your ~/.wyrdrc to use REM templates like this:

    set timed_template="REM %monname% %mday% %year% <++>AT %hour%:%min%<++> DURATION 1:00<++> MSG %\"<++>%\" %b"
    set untimed_template="REM %monname% %mday% %year% <++>MSG %\"<++>%\" %b"

    With this change, hitting Ctrl-J inside Vim (in insert mode) will cause your cursor to jump directly to the <++> markers, enabling you to quickly add any desired Remind delta and message parameters.

  • The 43 Folders Wiki has a page on Wyrd. This is a good place to look for other usage tips.

6  Licensing

Wyrd is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL), Version 2, as published by the Free Software Foundation. You should have received a copy of the GPL along with this program, in the file ’COPYING’.

7  Acknowledgments

Thanks, of course, to David Skoll for writing such a powerful reminder system. Thanks also to Nicolas George, who wrote the OCaml curses bindings used within Wyrd.

8  Contact info

Wyrd author: Paul Pelzl <pelzlpj@eecs.umich.edu>
Wyrd website: http://www.eecs.umich.edu/~pelzlpj/wyrd

Feel free to contact me if you have bugs, feature requests, patches, etc. I would also welcome volunteers interested in packaging Wyrd for various platforms.

Wyrd is developed with the aid of the excellent Bazaar VCS. Interested developers are advised to track Wyrd development via my public repository:
       http://www.eecs.umich.edu/~pelzlpj/wyrd/bzr-repo/
Primary development may be found on branch wyrd-1.4-dev .

9  Miscellaneous

“Wyrd is a concept in ancient Anglo-saxon and Nordic cultures roughly corresponding to fate.” – Wikipedia


1
The next_reminder operation locates reminders at the point they occur; if advance_warning is enabled, next_reminder will skip over any displayed warnings of an event.

This document was translated from LATEX by HEVEA.
wyrd-1.4.4/doc/Makefile0000644000175000017500000000206310757447265013420 0ustar paulpaul# Wyrd documentation makefile all: manual.pdf manual.html post-build-cleanup wyrd.1 wyrdrc.5 src/manual.ps: dvi dvips -tletterSize -Ppdf -G0 -o $@ src/manual.dvi dvi: src/manual.tex cd src && latex manual.tex && latex manual.tex src/manual.tex: src/manual.tex.in latex2man -CLATEX -L $< $@ manual.pdf: src/manual.ps ps2pdf13 $< $@ manual.html: src/manual.tex cd src && hevea -fix manual.tex && hevea -fix manual.tex cp src/manual.html . src/manual.tex.stripped: src/manual.tex.in python src/remove-tt.py $< $@ wyrd.1: src/manual.tex.stripped latex2man -M $< $@ wyrdrc.5: src/manual.tex.stripped latex2man -CWYRDRC -M $< $@ post-build-cleanup: manual.pdf manual.html wyrd.1 wyrdrc.5 cd src && rm -f *.aux *.log *.toc *.haux *.htoc *.dvi *.ps *.stripped *.html manual.tex clean: rm -f manual.tex *.aux *.log *.toc *.haux *.htoc *.dvi *.ps *.pdf *.html *.stripped wyrd.1 wyrdrc.5 cd src && rm -f manual.tex *.aux *.log *.toc *.haux *.htoc *.dvi *.ps *.pdf *.html *.stripped wyrd.1 wyrdrc.5 # arch-tag: DO_NOT_CHANGE_a5d62ea3-3a73-4de2-a2b3-a70bb310823f wyrd-1.4.4/doc/src/0000755000175000017500000000000010757447275012547 5ustar paulpaulwyrd-1.4.4/doc/src/manual.tex.in0000644000175000017500000012466210757447265015165 0ustar paulpaul% Wyrd documentation % % Notes: % This document is designed to be processed with the 'latex2man' perl % script. This script has a preprocessor, which is the source of the % IF LATEX ... ELSE ... END IF comments. % "latex2man -CLATEX -L" will output pure tex source, which can be % handled either via latex or hevea. (Also, latex2man sucks. If you know % of a better tool that does the same job, I'd love to hear about it.) % Hevea has its own preprocessor, which is the source of the BEGIN LATEX % and HEVEA comments. (Hevea doesn't suck.) \documentclass[11pt,notitlepage]{article} %@% IF LATEX %@% \usepackage{times} \usepackage{fullpage} %@% ELSE %@% \usepackage{latex2man} \setVersion{1.4} %@% END-IF %@% % End preamble %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} %@% IF LATEX %@% \title{Wyrd v1.4 User Manual} \author{Paul J. Pelzl} \date{August 17, 2007} \maketitle \begin{center} \emph{``Because you're tired of waiting for your bloated calendar program to start up.''} \end{center} \tableofcontents \clearpage \section{Introduction} Wyrd is a text-based front-end to Remind, a sophisticated calendar and alarm program available from %BEGIN LATEX Roaring Penguin Software, Inc.\footnote{http://www.roaringpenguin.com/penguin/open\_source\_remind.php} %END LATEX %HEVEA \begin{rawhtml} Roaring Penguin Software, Inc. \end{rawhtml} Wyrd serves two purposes: \begin{enumerate} \item It displays reminders in a scrollable timetable view suitable for visualizing your calendar at a glance. \item It makes creating and editing reminders fast and easy. However, Wyrd does not hide Remind's textfile programmability, for this is what makes Remind a truly powerful calendaring system. \end{enumerate} Wyrd also requires only a fraction of the resources of most calendar programs available today. \section{Installation} This section describes how to install Wyrd by compiling from source. Volunteers have pre-packaged Wyrd for several popular operating systems, so you may be able to save yourself some time by installing from those packages. Please check the %BEGIN LATEX Wyrd website\footnote{http://www.eecs.umich.edu/\~{}pelzlpj/wyrd} %END LATEX %HEVEA \begin{rawhtml} Wyrd website \end{rawhtml} for up-to-date package information. Wyrd is designed to be portable to most Unix-like operating systems, including GNU/Linux, *BSD, and Mac OS X. Before installing Wyrd, your system must have the following software installed: \begin{itemize} \item %BEGIN LATEX OCaml\footnote{http://caml.inria.fr} $\ge$ 3.08 %END LATEX %HEVEA \begin{rawhtml} OCaml >= 3.08 \end{rawhtml} \item %BEGIN LATEX the ncurses library\footnote{http://www.gnu.org/software/ncurses/ncurses.html} %END LATEX %HEVEA \begin{rawhtml} ncurses library \end{rawhtml} (and development headers) \item %BEGIN LATEX Remind \footnote{http://www.roaringpenguin.com/penguin/open\_source\_remind.php} $\ge$ 3.1.0 %END LATEX %HEVEA \begin{rawhtml} Remind >= 3.1.0 \end{rawhtml} \item %BEGIN LATEX GNU make\footnote{http://www.gnu.org/software/make/} %END LATEX %HEVEA \begin{rawhtml} GNU make \end{rawhtml} \item standard Unix utilities such as \texttt{cat}, \texttt{sort}, and \texttt{less} \end{itemize} Wyrd may be compiled by executing the following at the root of the source tree: \begin{verbatim} ./configure make \end{verbatim} After compiling, become root and execute \begin{verbatim} make install \end{verbatim} to complete the installation process. The \texttt{make} command here should correspond to GNU make; on some systems (particularly *BSD), you may need to use \texttt{gmake}. If your ncurses library was built with wide character support, Wyrd can be configured to render UTF-8 encoded reminders. To enable this option, use the command \begin{verbatim} ./configure --enable-utf8 \end{verbatim} when configuring the sources. %@% ELSE %@% %@% IF WYRDRC %@% \begin{Name}{5}{wyrdrc}{Paul J. Pelzl}{configuration file for the Wyrd calendar application}{wyrdrc manpage} \texttt{wyrdrc} is the configuration textfile for the \Cmd{wyrd}{1} console calendar application. \end{Name} %@% ELSE %@% \begin{Name}{1}{wyrd}{Paul J. Pelzl}{a console calendar application}{Wyrd 1.4 Manpage} \Prog{wyrd} is a text-based front-end to \Cmd{remind}{1}, a sophisticated calendar and alarm program. \end{Name} \section{Synopsis} \Prog{wyrd} \oArg{OPTIONS} \oArg{FILE} \section{Description} Open the calendar and display reminders defined in FILE (and any included reminder files). The default reminder file is \Tilde /.reminders. \section{Options} \begin{description} \item[\Opt{--version}] Display version information and exit. \item[\Opt{--help}] Display usage information. \item[\Opt{--add EVENT}] Add given event to reminders file and exit. \item[\Opt{--a EVENT}] Add given event to reminders file and exit. \end{description} %@% END-IF %@% %@% END-IF %@% %@% IF !WYRDRC %@% \section{Quick Start} %@% IF !LATEX %@% CAUTION: while this manpage should be suitable as a quick reference, it may be subject to miscellaneous shortcomings in typesetting. The definitive documentation is the user manual provided with Wyrd in PDF or HTML format. %@% ELSE %@% %@% END-IF %@% This section describes how to use Wyrd in its default configuration. After familiarizing yourself with the basic operations as outlined in this section, you may wish to consult %@% IF LATEX %@% Section \ref{advanced} %@% ELSE %@% the \Cmd{wyrdrc}{5} manpage %@% END-IF %@% to see how Wyrd can be configured to better fit your needs. \subsection{Overview} Before attemping to use Wyrd, learn how to use Remind. Wyrd makes no attempt to hide the details of Remind programming from the user. %@% IF LATEX %@% Aside from reading the Remind manpage, you may get some useful pointers by reading %BEGIN LATEX Mike Harris's article on 43 Folders\footnote{http://www.43folders.com/2005/02/guest\_mike\_harr.html} or David Skoll's writeup on Linux Journal\footnote{http://www.linuxjournal.com/article/3529}. The 43 Folders Wiki also has a nice section on Remind\footnote{http://wiki.43folders.com/index.php/Remind}. %END LATEX %HEVEA \begin{rawhtml} Mike Harris's article on 43 folders \end{rawhtml} %HEVEA \begin{rawhtml} or David Skoll's writeup on Linux Journal.\end{rawhtml} %HEVEA \begin{rawhtml} The 43 Folders Wiki also has a nice section on Remind.\end{rawhtml} You can launch Wyrd using the default reminder file by executing \texttt{wyrd}. If desired, a different reminder file may be selected by executing \texttt{wyrd }. %@% ELSE %@% %@% END-IF %@% At the top of the window is a short (incomplete) list of keybindings. The left window displays a scrollable timetable view, with reminders highlighted in various colors. If the \texttt{DURATION} specifier is used for a reminder, the highlighted area is rendered with an appropriate size. Overlapping reminders are rendered using one of four different indentation levels so that all reminders are at least partially visible. If the current time is visible in this window, it is highlighted in red. The upper right window displays a month calendar, with the color of each day representing the number of reminders it contains. The colors range across shades of white to blue to magenta as the number of reminders increases. The selected date is highlighted in cyan; if the current date is visible, it is highlighted in red. The lower right window displays a list of the untimed reminders falling on the selected date. The bottom window displays the full text of the \texttt{MSG} for the reminder or reminders that are currently selected. \subsection{Navigation} %@% IF LATEX %@% \begin{center} \begin{tabular}[t]{|l|l|} %@% ELSE %@% \begin{Table}{2} %@% END-IF %@% \hline Action & Keypress \\ \hline scroll up and down the schedule & \texttt{}, \texttt{} or \texttt{k}, \texttt{j} \\ jump back or forward by a day & \texttt{}, \texttt{} or \texttt{4}, \texttt{6} or \texttt{<}, \texttt{>} or \texttt{H}, \texttt{L} \\ jump back or forward by a week & \texttt{8}, \texttt{2} or \texttt{[}, \texttt{]} or \texttt{K}, \texttt{J} \\ jump back or forward by a month & \texttt{\{}, \texttt{\}} \\ jump to current date and time & \texttt{} \\ jump to the next reminder & \texttt{} \\ switch between schedule and untimed reminders window & \texttt{}, \texttt{} or \texttt{h}, \texttt{l} \\ zoom in on the schedule & \texttt{z} \\ scroll the description window up and down & \texttt{d}, \texttt{D} \\ \hline %@% IF LATEX %@% \end{tabular} \end{center} %@% ELSE %@% \end{Table} %@% END-IF %@% Notice that if you have a numeric keypad, the \{\texttt{4, 6, 8, 2}\} keys will let you move directionally in the month calendar view at the upper-right of the screen. Similarly, \{\texttt{H, J, K, L}\} will cause directional calendar movement using the standard mapping from %@% IF LATEX %@% \texttt{vi(1)}. %@% ELSE %@% \Cmd{vi}{1}. %@% END-IF %@% In addition to the hotkeys provided above, Wyrd lets you jump immediately to a desired date by pressing \texttt{'g'}, entering in a date specifier, and then pressing \texttt{}. Any of the following date specifiers may be used: \begin{itemize} \item 8 digits representing year, month, and day: YYYYMMDD \item 4 digits representing month and day (of current year): MMDD \item 2 digits representing day (of current month and year): DD \end{itemize} (The date specifier format may be changed to DDMMYYYY; consult %@% IF LATEX %@% Section \ref{variables}. %@% ELSE %@% the section on CONFIGURATION VARIABLES. %@% END-IF %@% ) \subsection{Editing Reminders} Note: By default, Wyrd is configured to modify your reminder files using the text editor specified by the \texttt{\$EDITOR} environment variable. (This configuration has been tested successfully with a number of common settings for \texttt{\$EDITOR}, including \texttt{'vim'}, \texttt{'emacs'}, and \texttt{'nano'}.) If you wish to use a different editor, see %@% IF LATEX %@% Section \ref{advanced}. %@% ELSE %@% the \Cmd{wyrdrc}{5} manpage. %@% END-IF %@% If you select a timeslot in the schedule view, then hit \texttt{'t'}, you will begin creating a new timed reminder. Wyrd will open up your reminder file in your favorite editor and move the cursor to the end of the file, where a new reminder template has been created. The template has the selected date and time filled in, so in many cases you will only need to fill in a \texttt{MSG} value. Similarly, hitting \texttt{'u'} will begin creating an untimed reminder. \texttt{'w'} will create a weekly timed reminder, and \texttt{'W'} will create a weekly untimed reminder; \texttt{'m'} will create a monthly timed reminder, and \texttt{'M'} will create a monthly untimed reminder. \texttt{'T'} and \texttt{'U'} also create timed and untimed reminders (respectively), but first will provide a selection dialog for you to choose which reminder file you want to add this reminder to. The set of reminder files is determined by scanning the \texttt{INCLUDE} lines in your default reminder file. If you select a reminder (either timed or untimed) and hit \texttt{}, you will begin editing that reminder. Wyrd will open up the appropriate reminders file in your editor and move the cursor to the corresponding \texttt{REM} line. If you select a timeslot that contains multiple overlapping reminders, Wyrd will provide a dialog that allows you to select the desired reminder. If you hit \texttt{} on a blank timeslot, Wyrd will begin creating a new timed or untimed reminder (depending on whether the timed or the untimed window is selected). Finally, pressing \texttt{'e'} will open the reminder file in your editor without attempting to select any particular reminder. \subsection{Quick Reminders} Wyrd offers an additional mode for entering simple reminders quickly. Press \texttt{'q'}, and you will be prompted for an event description. Simply enter a description for the event using natural language, then press \texttt{}. Examples: \begin{itemize} \item meeting with Bob tomorrow at 11 \item drop off package at 3pm \item wednesday 10am-11:30 go grocery shopping \item Board game night 20:15 next Fri \item 7/4 independence day \item 7/4/2007 independence day (next year) \item independence day (next year) on 2007-07-04 \end{itemize} If your event description can be understood, Wyrd will immediately create the reminder and scroll the display to its location. Currently the quick reminder mode tends to favor USA English conventions, as generalizing the natural language parser would require some work. Wyrd also allows you to use the "quick reminder" syntax to create new reminders from the command line, using the \texttt{-a} or \texttt{--add} options. For example, \begin{verbatim} wyrd --add "dinner with neighbors tomorrow at 7pm" \end{verbatim} would create a new reminder for tomorrow evening. When used in this mode, Wyrd exits silently with error code 0 if the reminder was successfully created. If the reminder could not be created (e.g. if the reminder syntax could not be parsed), Wyrd prints an error message and exits with a nonzero error code. \subsection{Cutting and Pasting Reminders} Reminders can be easily duplicated or rescheduled through the use of Wyrd's cutting and pasting features. Selecting a reminder and pressing \texttt{'X'} will cut that reminder: the corrdsponding \texttt{REM} line is deleted from your reminders file, and the reminder is copied to Wyrd's clipboard. To copy a reminder without deleting it, use \texttt{'y'} instead. To paste a reminder from the clipboard back into your schedule, just move the cursor to the desired date/time and press \texttt{'p'}. Wyrd will append a new \texttt{REM} line to the end of your reminders file, and open the file with your editor. The \texttt{REM} line will be configured to trigger on the selected date. If the copied reminder was timed, then the pasted reminder will be set to trigger at the selected time using the original \texttt{DURATION} setting. (Additional Remind settings such as \texttt{delta} and \texttt{tdelta} are not preserved by copy-and-paste.) If you wish to paste a reminder into a non-default reminders file, use \texttt{'P'}. This will spawn a selection dialog where you can choose the file that will hold the new reminder. WARNING: Cutting a reminder will delete only the single \texttt{REM} command responsible for triggering it. If you are using more complicated Remind scripting techniques to generate a particular reminder, then the \texttt{cut} operation may not do what you want. \subsection{Viewing Reminders} Aside from viewing reminders as they fall in the schedule, you can press \texttt{'r'} to view all reminders triggered on the selected date in a %@% IF LATEX %@% \texttt{less(1)} %@% ELSE %@% \Cmd{less}{1} %@% END-IF %@% window. Similarly, \texttt{'R'} will view all reminders triggered on or after the selected date (all non-expired reminders are triggered). If you want to get a more global view of your schedule, Wyrd will also let you view Remind's formatted calendar output in a %@% IF LATEX %@% \texttt{less(1)} %@% ELSE %@% \Cmd{less}{1} %@% END-IF %@% window. Pressing \texttt{'c'} will view a one-week calendar that contains the selected date, while pressing \texttt{'C'} will view a one-month calendar containing the selected date. \subsection{Searching for Reminders} Wyrd allows you to search for reminders with \texttt{MSG} values that match a search string. Press \texttt{'/'} to start entering a (case insensitive) regular expression. After the expression has been entered, press \texttt{} and Wyrd will locate the next reminder that matches the regexp. Press \texttt{'n'} to repeat the same search. Entry of a search string may be cancelled with \texttt{}. The regular expression syntax is Emacs-compatible. Note: Sorry, there is no "search backward" function. The search function requires the use of \texttt{"remind -n"}, which operates only forward in time. For the same reason, there is a command to jump forward to the next reminder, but no command to jump backward to the previous reminder. \subsection{Other Commands} A list of all keybindings may be viewed by pressing \texttt{'?'}. You can exit Wyrd by pressing \texttt{'Q'}. If the screen is corrupted for some reason, hit \texttt{'Ctrl-L'} to refresh the display. \subsection{Alarm Strategies} You may wish to generate some sort of alarm when a reminder is triggered. Wyrd does not offer any special alarm functionality, because Remind can handle the job already. Check the Remind manpage and consider how the \texttt{-k} option could be used to generate alarms with the aid of external programs. For example, the following command will generate a popup window using \texttt{gxmessage(1)} whenever a timed reminder is triggered: \begin{verbatim} remind -z -k'gxmessage -title "reminder" %s &' ~/.reminders & \end{verbatim} (A sensible way to start this alarm command is to place it in \texttt{\~{}.xinitrc} so that it launches when the X server is started.) If you want some advance warning (say, 15 minutes), you can cause Remind to trigger early by setting a \texttt{tdelta} in the AT clause: \begin{verbatim} REM Nov 27 2005 AT 14:30 +15 MSG Do something \end{verbatim} Alternatively, if you want to generate alarms only for specific reminders, consider using Remind's \texttt{RUN} command. This process could be easily automated by using the \texttt{template\emph{N}} configuration variables described in %@% IF LATEX %@% Section \ref{advanced}. %@% ELSE %@% the \Cmd{wyrdrc}{5} manpage. %@% END-IF %@% \subsection{Miscellaneous} Remind's \texttt{TAG} specifier may be used to cause Wyrd to give special treatment to certain reminders. If a reminder line includes the clause \texttt{"TAG noweight"}, then Wyrd will not give that reminder any weight when determining the ``busy level'' colorations applied to the month calendar. If a reminder line includes the clause \texttt{"TAG nodisplay"}, then Wyrd will neither display that reminder nor give it any weight when determining the month calendar colorations. The tag parameters are case insensitive. WARNING: These tag parameters are not guaranteed to interact well with other Remind front-ends such as tkremind. %@% END-IF %@% % (!WYRDRC) %@% IF LATEX || WYRDRC %@% %@% IF LATEX %@% \section{Advanced Configuration} \label{advanced} %@% ELSE %@% \section{Introduction} CAUTION: while this manpage should be suitable as a quick reference, it may be subject to miscellaneous shortcomings in typesetting. The definitive documentation is the user manual provided with Wyrd in PDF format. %@% END-IF %@% Wyrd reads a run-configuration textfile (generally \texttt{/etc/wyrdrc} or \texttt{/usr/local/etc/wyrdrc}) to determine key bindings, color schemes, and many other settings. You can create a personalized configuration file in \texttt{\$HOME/.wyrdrc}, and select settings that match your usage patterns. The recommended procedure is to ``include'' the \texttt{wyrdrc} file provided with Wyrd %@% IF LATEX %@% (see Section \ref{include}), %@% ELSE %@% (see INCLUDING OTHER RCFILES), %@% END-IF %@% and add or remove settings as desired. %@% IF LATEX %@% \subsection{\texttt{wyrdrc} Syntax} %@% ELSE %@% \section{\texttt{wyrdrc} Syntax} %@% END-IF %@% You may notice that the \texttt{wyrdrc} syntax is similar to the syntax used in the configuration file for the Mutt email client (muttrc). Within the \texttt{wyrdrc} file, strings should be enclosed in double quotes (\texttt{"}). A double quote character inside a string may be represented by %@% IF LATEX %@% \texttt{$\backslash$"} . %@% ELSE %@% \Bs " . %@% END-IF %@% The backslash character must be represented by doubling it %@% IF LATEX %@% (\texttt{$\backslash\backslash$}). %@% ELSE %@% (\Bs\Bs). %@% END-IF %@% %@% IF LATEX %@% \subsubsection{Including Other Rcfiles} \label{include} Syntax: \texttt{include \emph{filename\_string}} \\ \\ %@% ELSE %@% \subsection{Including Other Rcfiles} Syntax: include \emph{filename\_string} \\ \\ %@% END-IF %@% This syntax can be used to include one run-configuration file within another. This command could be used to load the default \texttt{wyrdrc} file (probably found in \texttt{/etc/wyrdrc} or \texttt{/usr/local/etc/wyrdrc}) within your personalized rcfile, %@% IF LATEX %@% \texttt{\~{}/.wyrdrc}. %@% ELSE %@% \Tilde /.wyrdrc . %@% END-IF %@% The filename string should be enclosed in quotes. %@% IF LATEX %@% \subsubsection{Setting Configuration Variables} \label{setvar} Syntax: \texttt{set \emph{variable}=\emph{value\_string}} \\ \\ %@% ELSE %@% \subsection{Setting Configuration Variables} Syntax: set \emph{variable}=\emph{value\_string} \\ \\ %@% END-IF %@% A number of configuration variables can be set using this syntax; check %@% IF LATEX %@% Section \ref{variables} %@% ELSE %@% the CONFIGURATION VARIABLES description %@% END-IF %@% to see a list. The variables are unquoted, but the values should be quoted strings. %@% IF LATEX %@% \subsubsection{Creating Key Bindings} \label{bindings} Syntax: \texttt{bind \emph{key\_identifier operation}} \\ \\ %@% ELSE %@% \subsection{Creating Key Bindings} Syntax: bind \emph{key\_identifier operation} \\ \\ %@% END-IF %@% This command will bind a keypress to execute a calendar operation. The various operations, which should not be enclosed in quotes, may be found in %@% IF LATEX %@% Section \ref{operationslist}. %@% ELSE %@% the section on CALENDAR OPERATIONS. %@% END-IF %@% Key identifiers may be specified by strings that represent a single keypress, for example \texttt{"m"} (quotes included). The key may be prefixed with %@% IF LATEX %@% \texttt{"$\backslash\backslash$C"} or \texttt{"$\backslash\backslash$M"} %@% ELSE %@% "\Bs\Bs C" or "\Bs\Bs M" %@% END-IF %@% to represent Control or Meta (Alt) modifiers, respectively; note that the backslash must be doubled. A number of special keys lack single-character representations, so the following strings may be used to represent them: \begin{itemize} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} \item \texttt{""} to \texttt{""} \end{itemize} Due to differences between various terminal emulators, this key identifier syntax may not be adequate to describe every keypress. As a workaround, Wyrd will also accept key identifiers in octal notation. As an example, you could use %@% IF LATEX %@% \texttt{$\backslash$024} %@% ELSE %@% \Bs 024 %@% END-IF %@% (do \emph{not} enclose it in quotes) to represent Ctrl-T. Multiple keys may be bound to the same operation, if desired. %@% IF LATEX %@% \subsubsection{Removing Key Bindings} \label{unbindings} Syntax: \texttt{unbind \emph{key\_identifier}} \\ \\ %@% ELSE %@% \subsection{Removing Key Bindings} Syntax: unbind \emph{key\_identifier} \\ \\ %@% END-IF %@% This command will remove all bindings associated with the key identifier. The key identifiers should be defined using the syntax described in the previous section. %@% IF LATEX %@% \subsubsection{Setting the Color Scheme} \label{colors} Syntax: \texttt{color \emph{object} \emph{foreground} \emph{background}} \\ \\ %@% ELSE %@% \subsection{Setting the Color Scheme} Syntax: color \emph{object} \emph{foreground} \emph{background} \\ \\ %@% END-IF %@% This command will apply the specified foreground and background colors to the appropriate object. A list of colorable objects is provided in %@% IF LATEX %@% Section \ref{colorable objects}. %@% ELSE %@% the section on COLORABLE OBJECTS. %@% END-IF %@% Wyrd will recognize the following color keywords: \texttt{black, red, green, yellow, blue, magenta, cyan, white, default}. The \texttt{default} keyword allows you to choose the default foreground or background colors. If you use \texttt{default} for your background color, this will access the transparent background on terminal emulators which support it. %@% IF LATEX %@% \subsection{Configuration Variables} \label{variables} The following configuration variables may be set as described in Section \ref{setvar}: %@% ELSE %@% \section{Configuration Variables} The following configuration variables may be set as described in the SETTING CONFIGURATION VARIABLES section. %@% END-IF %@% \begin{itemize} \item \texttt{remind\_command} \\ Determines the command used to execute Remind. \item \texttt{reminders\_file} \\ Controls which Remind file Wyrd will operate on. The default is %@% IF LATEX %@% \~{}/.reminders . %@% ELSE %@% \Tilde /.reminders . %@% END-IF %@% \item \texttt{edit\_old\_command} \\ Controls the command used to edit a pre-existing reminder. The special strings \texttt{'\%file\%'} and \texttt{'\%line\%'} will be replaced with a filename to edit and a line number to navigate to within that file. \item \texttt{edit\_new\_command} \\ Controls the command used to edit a new reminder. The special character \texttt{'\%file\%'} will be replaced with a filename to edit. Ideally, this command should move the cursor to the last line of the file, where the new reminder template is created. \item \texttt{edit\_any\_command} \\ Controls the command used for editing a reminder file without selecting any particular reminder. The special character \texttt{'\%file\%'} will be replaced with a filename to edit. \item \texttt{timed\_template} \\ Controls the format of the \texttt{REM} line created when editing a new timed reminder. The following string substitutions will be made: \texttt{'\%monname\%'} - month name, \texttt{'\%mon\%'} - month number, \texttt{'\%mday\%'} - day of the month, \texttt{'\%year\%'} - year, \texttt{'\%hour\%'} - hour, \texttt{'\%min\%'} - minute, \texttt{'\%wdayname\%'} - weekday name, \texttt{'\%wday\%'} - weekday number. \item \texttt{untimed\_template} \\ Controls the format of the \texttt{REM} line created when editing a new untimed reminder. The substitution syntax is the same as for \texttt{timed\_template}. %@% IF LATEX %@% \item \texttt{template\emph{N}} \\ %@% ELSE %@% \item template\emph{N} \\ %@% END-IF %@% Controls the format of a generic user-defined \texttt{REM} line template; \emph{N} may range from 0 to 9. The substitution syntax is the same as for \texttt{timed\_template}. \item \texttt{busy\_algorithm} \\ An integer value specifying which algorithm to use for measuring how busy the user is on a particular day. If \texttt{busy\_algorithm="1"}, then Wyrd will simply count the total number of reminders triggered on that day. If \texttt{busy\_algorithm="2"}, then Wyrd will count the number of hours of reminders that fall on that day. (Untimed reminders are assumed to occupy \texttt{untimed\_duration} minutes.) \item \texttt{untimed\_duration} \\ An integer value that specifies the assumed duration of an untimed reminder, in minutes. This is used only when computing the busy level with \texttt{busy\_algorithm="2"}. \item \texttt{busy\_level1} \\ An integer value specifying the maximum number of reminders in a day (with \texttt{busy\_algorithm="1"}) or maximum hours of reminders in a day (with \texttt{busy\_algorithm="2"}) which will be colored using the color scheme for \texttt{calendar\_level1}. \item \texttt{busy\_level2} \\ Same as above, using the \texttt{calendar\_level2} color scheme. \item \texttt{busy\_level3} \\ Same as above, using the \texttt{calendar\_level2} color scheme rendered in bold. \item \texttt{busy\_level4} \\ Same as above, using the \texttt{calendar\_level3} color scheme. Any day with more reminders than this will be rendered using the \texttt{calendar\_level3} color scheme rendered in bold. \item \texttt{week\_starts\_monday} \\ A boolean value (\texttt{"true"} or \texttt{"false"}) that determines the first day of the week. \item \texttt{schedule\_12\_hour} \\ A boolean value that determines whether the timed reminders window is drawn using 12- or 24-hour time. \item \texttt{selection\_12\_hour} \\ A boolean value that determines whether the selection information is drawn with 12- or 24-hour time. \item \texttt{status\_12\_hour} \\ A boolean value that determines whether the current time is drawn using a 12- or 24-hour clock. \item \texttt{description\_12\_hour} \\ A boolean value that determines whether reminder start and end times are drawn using 12- or 24-hour time in the description window. This value also controls the format of timestamps in the formatted calendars produced by \texttt{view\_week} and \texttt{view\_month}. \item \texttt{center\_cursor} \\ A boolean value that determines how the screen and cursor move during scrolling operations. When set to \texttt{"true"}, the cursor is fixed in the center of the timed reminders window, and the schedule scrolls around it. When set to \texttt{"false"} (the default), the cursor will move up and down the schedule during scrolling operations. \item \texttt{goto\_big\_endian} \\ A boolean value that determines how the the \texttt{goto} operation will parse dates. When set to \texttt{"true"}, date specifiers should be in ISO 8601 (YYYYMMDD) format. When set to \texttt{"false"}, date specifiers should be in European style DDMMYYYY format. \item \texttt{quick\_date\_US} \\ A boolean value that determines how the \texttt{quick\_add} operation will parse numeric dates with slashes, e.g. 6/1 (or 6/1/2006). When set to \texttt{"true"}, the first number is a month and the second is the day of the month (June 1). When set to \texttt{"false"}, these meanings of these two fields are switched (January 6). \item \texttt{number\_weeks} \\ A boolean value that determines whether or not weeks should be numbered within the month calendar window. Weeks are numbered according to the ISO 8601 standard. The ISO standard week begins on Monday, so to avoid confusion it is recommended that \texttt{week\_starts\_monday} be set to \texttt{"true"} when week numbering is enabled. \item \texttt{home\_sticky} \\ A boolean value that determines whether or not the cursor should "stick" to the "home" position. When this option is set to \texttt{"true"}, then after pressing the \texttt{} key the cursor will automatically follow the current date and time. The effect is cancelled by pressing any of the navigation keys. \item \texttt{untimed\_window\_width} \\ An integer value that determines the target width of the month-calendar window and the untimed reminders window. The allowable range is 34 to (\texttt{\$COLUMNS} - 40) characters, and Wyrd will silently disregard any setting outside this range. \item \texttt{advance\_warning} \\ A boolean value that determines whether or not Wyrd should display advance warning of reminders. When set to \texttt{"true"}, Wyrd will invoke Remind in a mode that generates advance warning of reminders as specified in the reminder file. \item \texttt{untimed\_bold} \\ A boolean value that determines whether or not Wyrd should render untimed reminders using a bold font. \end{itemize} For maximum usefulness, \texttt{busy\_level1} $<$ \texttt{busy\_level2} $<$ \texttt{busy\_level3} $<$ \texttt{busy\_level4}. %@% IF LATEX %@% \subsection{Calendar Operations} \label{operationslist} %@% ELSE %@% \section{Calendar Operations} %@% END-IF %@% Every Wyrd operation can be made available to the interface using the syntax described in %@% IF LATEX %@% Section \ref{bindings}. %@% ELSE %@% the section on CREATING KEY BINDINGS. %@% END-IF %@% The following is a list of every available operation. \begin{itemize} \item \texttt{scroll\_up} \\ move the cursor up one element \item \texttt{scroll\_down} \\ move the cursor down one element \item \texttt{next\_day} \\ jump ahead one day \item \texttt{previous\_day} \\ jump backward one day \item \texttt{next\_week} \\ jump ahead one week \item \texttt{previous\_week} \\ jump backward one week \item \texttt{next\_month} \\ jump ahead one month \item \texttt{previous\_month} \\ jump backward one month \item \texttt{home} \\ jump to the current date and time \item \texttt{goto} \\ begin entering a date specifier to jump to \item \texttt{zoom} \\ zoom in on the day schedule view (this operation is cyclic) \item \texttt{edit} \\ edit the selected reminder \item \texttt{edit\_any} \\ edit a reminder file, without selecting any particular reminder \item \texttt{scroll\_description\_up} \\ scroll the description window contents up (when possible) \item \texttt{scroll\_description\_down} \\ scroll the description window contents down (when possible) \item \texttt{quick\_add} \\ add a ``quick reminder'' \item \texttt{new\_timed} \\ create a new timed reminder \item \texttt{new\_timed\_dialog} \\ same as previous, with a reminder file selection dialog \item \texttt{new\_untimed} \\ create a new untimed reminder \item \texttt{new\_untimed\_dialog} \\ same as previous, with a reminder file selection dialog %@% IF LATEX %@% \item \texttt{new\_template\emph{N}} \\ create a new user-defined reminder using \texttt{template\emph{N}}, where %@% ELSE %@% \item new\_template\emph{N} \\ create a new user-defined reminder using template\emph{N}, where %@% END-IF %@% \emph{N} may range from 0 to 9 %@% IF LATEX %@% \item \texttt{new\_template\emph{N}\_dialog} \\ %@% ELSE %@% \item new\_template\emph{N}\_dialog \\ %@% END-IF %@% same as previous, with a reminder file selection dialog \item copy \\ copy a reminder to Wyrd's clipboard \item cut \\ delete a reminder and copy it to Wyrd's clipboard \item paste \\ paste a reminder from Wyrd's clipboard into the schedule \item paste\_dialog \\ same as previous, with a reminder file selection dialog \item \texttt{switch\_window} \\ switch between the day schedule window on the left, and the untimed reminder window on the right \item \texttt{begin\_search} \\ begin entering a search string \item \texttt{search\_next} \\ search for the next occurrence of the search string \item \texttt{next\_reminder} \\ %@% IF LATEX %@% jump to the next reminder\footnote{The \texttt{next\_reminder} operation locates reminders at the point they occur; if \texttt{advance\_warning} is enabled, \texttt{next\_reminder} will skip over any displayed warnings of an event.} %@% ELSE %@% jump to the next reminder %@% END-IF %@% \item \texttt{view\_remind} \\ view the output of \texttt{remind} for the selected date \item \texttt{view\_remind\_all} \\ view the output of \texttt{remind} for the selected date, triggering all non-expired reminders \item \texttt{view\_week} \\ view Remind's formatted calendar for the week that contains the selected date (the in-calendar timestamp formats are determined by the value of \texttt{description\_12\_hour}) \item \texttt{view\_month} \\ view Remind's formatted calendar for the month that contains the selected date (the in-calendar timestamp formats are determined by the value of \texttt{description\_12\_hour}) \item \texttt{refresh} \\ refresh the display \item \texttt{quit} \\ exit Wyrd \item \texttt{entry\_complete} \\ signal completion of search string entry or date specifier \item \texttt{entry\_backspace} \\ delete the last character of the search string or date specifier \item \texttt{entry\_cancel} \\ cancel entry of a search string or date specifier \end{itemize} %@% IF LATEX %@% \subsection{Colorable Objects} \label{colorable objects} %@% ELSE %@% \section{Colorable Objects} %@% END-IF %@% Each of Wyrd's on-screen elements may be colored by the color scheme of your choice, using the syntax defined in %@% IF LATEX %@% Section \ref{colors}. %@% ELSE %@% the section on SETTING THE COLOR SCHEME. %@% END-IF %@% The following is a list of all colorable objects. \begin{itemize} \item \texttt{help} \\ the help bar at the top of the screen \item \texttt{timed\_default} \\ an empty timeslot in the day-schedule window \item \texttt{timed\_current} \\ the current time in the day-schedule window (if it is visible) \item \texttt{timed\_reminder1} \\ a nonempty timeslot in the day-schedule window, indented to level 1 \item \texttt{timed\_reminder2} \\ a nonempty timeslot in the day-schedule window, indented to level 2 \item \texttt{timed\_reminder3} \\ a nonempty timeslot in the day-schedule window, indented to level 3 \item \texttt{timed\_reminder4} \\ a nonempty timeslot in the day-schedule window, indented to level 4 \item \texttt{untimed\_reminder} \\ an entry in the untimed reminders window \item \texttt{timed\_date} \\ the vertical date strip at the left side of the screen \item \texttt{selection\_info} \\ the line providing date/time for the current selection \item \texttt{description} \\ the reminder description window \item \texttt{status} \\ the bottom bar providing current date and time \item \texttt{calendar\_labels} \\ the month and weekday labels in the calendar window \item \texttt{calendar\_level1} \\ calendar days with low activity \item \texttt{calendar\_level2} \\ calendar days with medium activity \item \texttt{calendar\_level3} \\ calendar days with high activity \item \texttt{calendar\_today} \\ the current day in the calendar window (if it is visible) \item \texttt{left\_divider} \\ the vertical line to the left of the timed reminders window \item \texttt{right\_divider} \\ the vertical and horizontal lines to the right of the timed reminders window \end{itemize} % end WYRDRC %@% END-IF %@% %@% IF !WYRDRC %@% \section{Usage Tips} \begin{itemize} \item Wyrd fills in sensible defaults for the fields of a \texttt{REM} statement, but you will inevitably need to make some small edits to achieve the behavior you want. If you use Vim, you can make your life easier by installing the Vim-Latex Suite and then modifying your %@% IF LATEX %@% \texttt{\~{}/.wyrdrc} %@% ELSE %@% \Tilde/.wyrdrc %@% END-IF %@% to use \texttt{REM} templates like this: %@% IF LATEX %@% \texttt{set timed\_template="REM \%monname\% \%mday\% \%year\% <++>AT \%hour\%:\%min\%<++> DURATION 1:00<++> MSG \%$\backslash$"<++>\%$\backslash$" \%b"} \\ \texttt{set untimed\_template="REM \%monname\% \%mday\% \%year\% <++>MSG \%$\backslash$"<++>\%$\backslash$" \%b"} %@% ELSE %@% \texttt{set timed\_template="REM \%monname\% \%mday\% \%year\% <++>AT \%hour\%:\%min\%<++> DURATION 1:00<++> MSG \%\Bs"<++>\%\Bs" \,\%b"} \\ \texttt{set untimed\_template="REM \%monname\% \%mday\% \%year\% <++>MSG \%\Bs"<++>\%\Bs" \,\%b"} %@% END-IF %@% With this change, hitting Ctrl-J inside Vim (in insert mode) will cause your cursor to jump directly to the \texttt{<++>} markers, enabling you to quickly add any desired Remind delta and message parameters. %@% IF LATEX %@% \item The 43 Folders Wiki %BEGIN LATEX has a page on Wyrd\footnote{http://wiki.43folders.com/index.php/Wyrd}. %END LATEX %HEVEA \begin{rawhtml} has a page on Wyrd. \end{rawhtml} This is a good place to look for other usage tips. %@% END-IF %@% \end{itemize} \section{Licensing} Wyrd is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL), Version 2, as published by the Free Software Foundation. You should have received a copy of the GPL along with this program, in the file \texttt{'COPYING'}. \section{Acknowledgments} Thanks, of course, to David Skoll for writing such a powerful reminder system. Thanks also to Nicolas George, who wrote the OCaml curses bindings used within Wyrd. %@% END-IF %@% \section{Contact info} Wyrd author: Paul Pelzl \texttt{} \\ %@% IF LATEX %@% Wyrd website: \texttt{http://www.eecs.umich.edu/\~{}pelzlpj/wyrd} \\ %@% ELSE %@% Wyrd website: \URL{http://www.eecs.umich.edu/\Tilde pelzlpj/wyrd} \\ %@% END-IF %@% %@% IF LATEX %@% \noindent Feel free to contact me if you have bugs, feature requests, patches, etc. I would also welcome volunteers interested in packaging Wyrd for various platforms. Wyrd is developed with the aid of the excellent %@% IF LATEX %@% %BEGIN LATEX Bazaar VCS\footnote{http://www.bazaar-vcs.org/}. %END LATEX %HEVEA \begin{rawhtml} Bazaar VCS. \end{rawhtml} %@% ELSE %@% Bazaar VCS [1]. %@% END-IF %@% Interested developers are advised to track Wyrd development via my public repository: \\ %@% IF LATEX %@% \hspace*{2cm} \texttt{http://www.eecs.umich.edu/\~{}pelzlpj/wyrd/bzr-repo/} \\ %@% ELSE %@% http://www.eecs.umich.edu/\Tilde pelzlpj/wyrd/bzr-repo/ \\ %@% END-IF %@% Primary development may be found on branch \texttt{wyrd-1.4-dev} . %@% END-IF %@% \section{Miscellaneous} ``Wyrd is a concept in ancient Anglo-saxon and Nordic cultures roughly corresponding to fate.'' \emph{-- Wikipedia} %@% IF !LATEX && !WYRDRC %@% \section{See Also} \Cmd{wyrdrc}{5}, \Cmd{remind}{1} %@% END-IF %@% %@% IF !LATEX %@% %@% IF WYRDRC %@% \section{See Also} \Cmd{wyrd}{1}, \Cmd{remind}{1} \section{Author} This manpage is written by Paul J. Pelzl . %@% END-IF %@% \LatexManEnd %@% END-IF %@% \end{document} % arch-tag: DO_NOT_CHANGE_db7ed8b2-8ea4-4e32-b0f6-50482487cb00 wyrd-1.4.4/doc/src/remove-tt.py0000644000175000017500000000075510757447265015051 0ustar paulpaul#!/usr/bin/env python # Strip out all the \texttt{} occurrences (not perfect, but good enough) import re, sys infilename = sys.argv[1] outfilename = sys.argv[2] infile = open(infilename, "r").read() tt_regex = re.compile("\\\\texttt\{([^}]+)}") def tt_replace(m): return m.group(1) replaced_string = re.sub(tt_regex, tt_replace, infile) outfile = open(outfilename, "w") outfile.write(replaced_string) outfile.close() # arch-tag: DO_NOT_CHANGE_97d4155d-0a4e-42ae-ae0a-0d064c1a7b71 wyrd-1.4.4/doc/TODO0000644000175000017500000000127310757447265012452 0ustar paulpaulWyrd To-Do list ---------------------------------------------------------------------------------- * Consider incremental searching. * Consider an Orpie-like abbreviation syntax for inputting commands. * Consider a more compact "maximum zoom" view that eliminates spaces between reminders--similar to Remind's formatted calendar, but formatted vertically like Wyrd's primary display. * When LINES is sufficiently large, consider adding a bit more month context in the calendar window at the upper right. * If advance warning is enabled, improve search performance by caching reminders with advance warning suppressed. # arch-tag: DO_NOT_CHANGE_13b859a4-395f-4c00-a604-d384b6490bbc wyrd-1.4.4/doc/wyrdrc.50000644000175000017500000003746210757447275013374 0ustar paulpaul'\" t .\" Manual page created with latex2man on Thu Feb 21 22:25:33 CST 2008 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "WYRDRC" "5" "21 February 2008" "configuration file for the Wyrd calendar application " "configuration file for the Wyrd calendar application " .SH NAME wyrdrc is the configuration textfile for the \fIwyrd\fP(1) console calendar application. .PP .SH INTRODUCTION CAUTION: while this manpage should be suitable as a quick reference, it may be subject to miscellaneous shortcomings in typesetting. The definitive documentation is the user manual provided with Wyrd in PDF format. .PP Wyrd reads a run\-configuration textfile (generally /etc/wyrdrc or /usr/local/etc/wyrdrc) to determine key bindings, color schemes, and many other settings. You can create a personalized configuration file in $HOME/.wyrdrc, and select settings that match your usage patterns. The recommended procedure is to ``include\&'' the wyrdrc file provided with Wyrd (see INCLUDING OTHER RCFILES), and add or remove settings as desired. .PP .SH WYRDRC SYNTAX You may notice that the wyrdrc syntax is similar to the syntax used in the configuration file for the Mutt email client (muttrc). .PP Within the wyrdrc file, strings should be enclosed in double quotes ("). A double quote character inside a string may be represented by \\" \&. The backslash character must be represented by doubling it (\\\\). .PP .SS INCLUDING OTHER RCFILES Syntax: include \fIfilename_string\fP .br .br This syntax can be used to include one run\-configuration file within another. This command could be used to load the default wyrdrc file (probably found in /etc/wyrdrc or /usr/local/etc/wyrdrc) within your personalized rcfile, ~/.wyrdrc \&. The filename string should be enclosed in quotes. .PP .SS SETTING CONFIGURATION VARIABLES Syntax: set \fIvariable\fP=\fIvalue_string\fP .br .br A number of configuration variables can be set using this syntax; check the CONFIGURATION VARIABLES description to see a list. The variables are unquoted, but the values should be quoted strings. .PP .SS CREATING KEY BINDINGS Syntax: bind \fIkey_identifier operation\fP .br .br This command will bind a keypress to execute a calendar operation. The various operations, which should not be enclosed in quotes, may be found in the section on CALENDAR OPERATIONS. Key identifiers may be specified by strings that represent a single keypress, for example "m" (quotes included). The key may be prefixed with "\\\\C" or "\\\\M" to represent Control or Meta (Alt) modifiers, respectively; note that the backslash must be doubled. A number of special keys lack single\-character representations, so the following strings may be used to represent them: .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" .TP .B * "" to "" .PP Due to differences between various terminal emulators, this key identifier syntax may not be adequate to describe every keypress. As a workaround, Wyrd will also accept key identifiers in octal notation. As an example, you could use \\024 (do \fInot\fP enclose it in quotes) to represent Ctrl\-T. .PP Multiple keys may be bound to the same operation, if desired. .PP .SS REMOVING KEY BINDINGS Syntax: unbind \fIkey_identifier\fP .br .br This command will remove all bindings associated with the key identifier. The key identifiers should be defined using the syntax described in the previous section. .PP .SS SETTING THE COLOR SCHEME Syntax: color \fIobject\fP \fIforeground\fP \fIbackground\fP .br .br This command will apply the specified foreground and background colors to the appropriate object. A list of colorable objects is provided in the section on COLORABLE OBJECTS. Wyrd will recognize the following color keywords: black, red, green, yellow, blue, magenta, cyan, white, default. The default keyword allows you to choose the default foreground or background colors. If you use default for your background color, this will access the transparent background on terminal emulators which support it. .PP .SH CONFIGURATION VARIABLES The following configuration variables may be set as described in the SETTING CONFIGURATION VARIABLES section. .TP .B * remind_command .br Determines the command used to execute Remind. .TP .B * reminders_file .br Controls which Remind file Wyrd will operate on. The default is ~/.reminders \&. .TP .B * edit_old_command .br Controls the command used to edit a pre\-existing reminder. The special strings \&'%file%\&' and \&'%line%\&' will be replaced with a filename to edit and a line number to navigate to within that file. .TP .B * edit_new_command .br Controls the command used to edit a new reminder. The special character \&'%file%\&' will be replaced with a filename to edit. Ideally, this command should move the cursor to the last line of the file, where the new reminder template is created. .TP .B * edit_any_command .br Controls the command used for editing a reminder file without selecting any particular reminder. The special character \&'%file%\&' will be replaced with a filename to edit. .TP .B * timed_template .br Controls the format of the REM line created when editing a new timed reminder. The following string substitutions will be made: \&'%monname%\&' \- month name, \&'%mon%\&' \- month number, \&'%mday%\&' \- day of the month, \&'%year%\&' \- year, \&'%hour%\&' \- hour, \&'%min%\&' \- minute, \&'%wdayname%\&' \- weekday name, \&'%wday%\&' \- weekday number. .TP .B * untimed_template .br Controls the format of the REM line created when editing a new untimed reminder. The substitution syntax is the same as for timed_template. .TP .B * template\fIN\fP .br Controls the format of a generic user\-defined REM line template; \fIN\fP may range from 0 to 9. The substitution syntax is the same as for timed_template. .TP .B * busy_algorithm .br An integer value specifying which algorithm to use for measuring how busy the user is on a particular day. If busy_algorithm="1", then Wyrd will simply count the total number of reminders triggered on that day. If busy_algorithm="2", then Wyrd will count the number of hours of reminders that fall on that day. (Untimed reminders are assumed to occupy untimed_duration minutes.) .TP .B * untimed_duration .br An integer value that specifies the assumed duration of an untimed reminder, in minutes. This is used only when computing the busy level with busy_algorithm="2". .TP .B * busy_level1 .br An integer value specifying the maximum number of reminders in a day (with busy_algorithm="1") or maximum hours of reminders in a day (with busy_algorithm="2") which will be colored using the color scheme for calendar_level1. .TP .B * busy_level2 .br Same as above, using the calendar_level2 color scheme. .TP .B * busy_level3 .br Same as above, using the calendar_level2 color scheme rendered in bold. .TP .B * busy_level4 .br Same as above, using the calendar_level3 color scheme. Any day with more reminders than this will be rendered using the calendar_level3 color scheme rendered in bold. .TP .B * week_starts_monday .br A boolean value ("true" or "false") that determines the first day of the week. .TP .B * schedule_12_hour .br A boolean value that determines whether the timed reminders window is drawn using 12\- or 24\-hour time. .TP .B * selection_12_hour .br A boolean value that determines whether the selection information is drawn with 12\- or 24\-hour time. .TP .B * status_12_hour .br A boolean value that determines whether the current time is drawn using a 12\- or 24\-hour clock. .TP .B * description_12_hour .br A boolean value that determines whether reminder start and end times are drawn using 12\- or 24\-hour time in the description window. This value also controls the format of timestamps in the formatted calendars produced by view_week and view_month. .TP .B * center_cursor .br A boolean value that determines how the screen and cursor move during scrolling operations. When set to "true", the cursor is fixed in the center of the timed reminders window, and the schedule scrolls around it. When set to "false" (the default), the cursor will move up and down the schedule during scrolling operations. .TP .B * goto_big_endian .br A boolean value that determines how the the goto operation will parse dates. When set to "true", date specifiers should be in ISO 8601 (YYYYMMDD) format. When set to "false", date specifiers should be in European style DDMMYYYY format. .TP .B * quick_date_US .br A boolean value that determines how the quick_add operation will parse numeric dates with slashes, e.g. 6/1 (or 6/1/2006). When set to "true", the first number is a month and the second is the day of the month (June 1). When set to "false", these meanings of these two fields are switched (January 6). .TP .B * number_weeks .br A boolean value that determines whether or not weeks should be numbered within the month calendar window. Weeks are numbered according to the ISO 8601 standard. The ISO standard week begins on Monday, so to avoid confusion it is recommended that week_starts_monday be set to "true" when week numbering is enabled. .TP .B * home_sticky .br A boolean value that determines whether or not the cursor should "stick" to the "home" position. When this option is set to "true", then after pressing the key the cursor will automatically follow the current date and time. The effect is cancelled by pressing any of the navigation keys. .TP .B * untimed_window_width .br An integer value that determines the target width of the month\-calendar window and the untimed reminders window. The allowable range is 34 to ($COLUMNS \- 40) characters, and Wyrd will silently disregard any setting outside this range. .TP .B * advance_warning .br A boolean value that determines whether or not Wyrd should display advance warning of reminders. When set to "true", Wyrd will invoke Remind in a mode that generates advance warning of reminders as specified in the reminder file. .TP .B * untimed_bold .br A boolean value that determines whether or not Wyrd should render untimed reminders using a bold font. .PP For maximum usefulness, busy_level1 < busy_level2 < busy_level3 < busy_level4. .PP .SH CALENDAR OPERATIONS Every Wyrd operation can be made available to the interface using the syntax described in the section on CREATING KEY BINDINGS. The following is a list of every available operation. .PP .TP .B * scroll_up .br move the cursor up one element .TP .B * scroll_down .br move the cursor down one element .TP .B * next_day .br jump ahead one day .TP .B * previous_day .br jump backward one day .TP .B * next_week .br jump ahead one week .TP .B * previous_week .br jump backward one week .TP .B * next_month .br jump ahead one month .TP .B * previous_month .br jump backward one month .TP .B * home .br jump to the current date and time .TP .B * goto .br begin entering a date specifier to jump to .TP .B * zoom .br zoom in on the day schedule view (this operation is cyclic) .TP .B * edit .br edit the selected reminder .TP .B * edit_any .br edit a reminder file, without selecting any particular reminder .TP .B * scroll_description_up .br scroll the description window contents up (when possible) .TP .B * scroll_description_down .br scroll the description window contents down (when possible) .TP .B * quick_add .br add a ``quick reminder\&'' .TP .B * new_timed .br create a new timed reminder .TP .B * new_timed_dialog .br same as previous, with a reminder file selection dialog .TP .B * new_untimed .br create a new untimed reminder .TP .B * new_untimed_dialog .br same as previous, with a reminder file selection dialog .TP .B * new_template\fIN\fP .br create a new user\-defined reminder using template\fIN\fP, where \fIN\fP may range from 0 to 9 .TP .B * new_template\fIN\fP_dialog .br same as previous, with a reminder file selection dialog .TP .B * copy .br copy a reminder to Wyrd\&'s clipboard .TP .B * cut .br delete a reminder and copy it to Wyrd\&'s clipboard .TP .B * paste .br paste a reminder from Wyrd\&'s clipboard into the schedule .TP .B * paste_dialog .br same as previous, with a reminder file selection dialog .TP .B * switch_window .br switch between the day schedule window on the left, and the untimed reminder window on the right .TP .B * begin_search .br begin entering a search string .TP .B * search_next .br search for the next occurrence of the search string .TP .B * next_reminder .br jump to the next reminder .TP .B * view_remind .br view the output of remind for the selected date .TP .B * view_remind_all .br view the output of remind for the selected date, triggering all non\-expired reminders .TP .B * view_week .br view Remind\&'s formatted calendar for the week that contains the selected date (the in\-calendar timestamp formats are determined by the value of description_12_hour) .TP .B * view_month .br view Remind\&'s formatted calendar for the month that contains the selected date (the in\-calendar timestamp formats are determined by the value of description_12_hour) .TP .B * refresh .br refresh the display .TP .B * quit .br exit Wyrd .TP .B * entry_complete .br signal completion of search string entry or date specifier .TP .B * entry_backspace .br delete the last character of the search string or date specifier .TP .B * entry_cancel .br cancel entry of a search string or date specifier .PP .SH COLORABLE OBJECTS Each of Wyrd\&'s on\-screen elements may be colored by the color scheme of your choice, using the syntax defined in the section on SETTING THE COLOR SCHEME. The following is a list of all colorable objects. .TP .B * help .br the help bar at the top of the screen .TP .B * timed_default .br an empty timeslot in the day\-schedule window .TP .B * timed_current .br the current time in the day\-schedule window (if it is visible) .TP .B * timed_reminder1 .br a nonempty timeslot in the day\-schedule window, indented to level 1 .TP .B * timed_reminder2 .br a nonempty timeslot in the day\-schedule window, indented to level 2 .TP .B * timed_reminder3 .br a nonempty timeslot in the day\-schedule window, indented to level 3 .TP .B * timed_reminder4 .br a nonempty timeslot in the day\-schedule window, indented to level 4 .TP .B * untimed_reminder .br an entry in the untimed reminders window .TP .B * timed_date .br the vertical date strip at the left side of the screen .TP .B * selection_info .br the line providing date/time for the current selection .TP .B * description .br the reminder description window .TP .B * status .br the bottom bar providing current date and time .TP .B * calendar_labels .br the month and weekday labels in the calendar window .TP .B * calendar_level1 .br calendar days with low activity .TP .B * calendar_level2 .br calendar days with medium activity .TP .B * calendar_level3 .br calendar days with high activity .TP .B * calendar_today .br the current day in the calendar window (if it is visible) .TP .B * left_divider .br the vertical line to the left of the timed reminders window .TP .B * right_divider .br the vertical and horizontal lines to the right of the timed reminders window .PP .SH CONTACT INFO Wyrd author: Paul Pelzl .br Wyrd website: \fBhttp://www.eecs.umich.edu/~pelzlpj/wyrd\fP .br .PP .SH MISCELLANEOUS ``Wyrd is a concept in ancient Anglo\-saxon and Nordic cultures roughly corresponding to fate.\&'' \fI\-\- Wikipedia\fP .PP .SH SEE ALSO \fIwyrd\fP(1), \fIremind\fP(1) .PP .SH AUTHOR This manpage is written by Paul J. Pelzl . .\" NOTE: This file is generated, DO NOT EDIT. wyrd-1.4.4/doc/manual.pdf0000644000175000017500000021712410757447273013735 0ustar paulpaul%PDF-1.3 %Çì¢ 5 0 obj <> stream xœí[Ûr[5á1_á7Ž,¤­ûcÛaʵ%ÀÃCHÒÔà$mêÊoÀ³u9ÖÖ9:nš¤Ôm:™LdE—-iií›ütÆ™˜ñð“ÿžî}öÐÎNžíñÙø{²÷tOijüçðtvwù™° „Ö³ýG{©³˜óÆÌŒÑLr;Û?Ýû¥ûyn%ã’Ëîåœcã­é.Žæ Ð8­…îE©¥È°(¸Þvªo«»±–K0ªîY(+ÂvÇ¡±ÖÞãÈ©±â¢û&Œf¤Å~¥ÁY™ãy)’«ùË ¥õ¿îßOkÌk-ÂZµdVr1[HΤ¸È#\ä÷s¡˜ ÂÄÞFHðq|!9Nå™qÐÝ-€+ W«X«%8ë®§ ²ŠB‚ÄžÇjí±©B.öµv†£1e@$©î„Ò‚k©¨,'¥HjŸ%± É:Kë]<’Ü–â§i—5¡Ôòf±tKÛéKÌãцí\iâe¶P‚9ã’àÿY¸æR+ÑÝM£ ÈtÐÊ9PÝa,z¯d<<®hˆ¢]÷¤ªVŠy+®!ìà"b³ü/•’\Uƒ¦]àBvëó²ãñ¬¥wRÛn}0P“x†:pSÄÔmú Õ–QáNŽ÷íßFi…HF*DÁ$Þ³ˆ`¼‚xW2‚Œ•f»;YiðBuça“ð^Y)ÂÔX>Îq¾ÏÞØn¢I"9c½/s—Ûƒ tŠ£_ïíò ÞÕ…÷ML÷e†>B‡N·É ü—œ+°-gT¢£Ø|ƒ(rËʼnÀ÷¯È’ö>#‚ȸKL+ÝŸ”¦‘·ú'âêé.±z¹©4PWÆG2çu]Kæžle‘ùAµkK²md.@ù¶™ZÀE¹h¤ICFYË•aY'v&µdÖY´9d÷p, ¯¢*߀ñt9e³‰R(j2èaÜösÞ]q"Á¡™ç{Ø©!ìrË-”§ ìÊ£¶hËj@Køæ gÐ-×ÑÑÞ…Þ±ßq í¹í´7Â_î”hO¶ð§ þîDQü­'}R¢wψñ×{¿ˆ® q<Û²¹me¯·•£­øpNö r3¼“×:F·µ\Ñ ¢áÝFÀ.ˆ“P(ð8'”ozÈÔ !šÈŸæ&Ä  øVÇÈIfÉ&.…¸AjÔÜ2«/ž÷í¼wWœK›cøyb6ùÐøU~9Á¡2 ¢¦SW˜RãÆd ±ÀMÏah§}U·8ÐrÁŒï9,þ_qb\Ñk¦Jèå5'ëQj(íGM$©[Ίk†hÖGhèQš0e¨Ž§¨;=ÔåUÝËÔm:åwXœí®Êt•«Ò¦F_@w§€n5A‡§}²cß¼8ûÀÍq0}HÑÑÈÿ’À8xÇF#‘½v4çvø.ˆsiWe„?êªLťˎbç¬ñ71Z£…Ô¾[Rß‚(d‚¢ÕjHuc+p*“Ü fíå"4·oMœˆ@.™ó:zy—Ã<[Ái•òQ%åC¨ñˆߋٔÎÚ*­sFSlmÀæ$lHsÞ+c3mùÃGtÒ“ È jfnÆßž»\2Ï^%é¤&.wÞwYå75Ã’êç N €´>%À5ÐqQ¹ö¨Y{¸©mH©€q¢ÒZ/«!Ù/Â%ÍÐÎÖú¶_ÁwYœžˆ^$t Ì#oËΉ9Tàá.¥¼u¾S;äIÅêù„ÉÝv_eô÷.`2ú-¥‘I3QÄPÚŠtD%'Ãí–oáØoÞzÅ­mXæ#äå–Mòl@ ô¦"nÌ*Ø)ÿ¶þˆê‘ZÁTaŒ•±5NÏÆy]÷Ó\Á4@n]‚q’"½[’úêS\ç<³×J÷Þ6¶œÃ6Ý }: AY HE1Aì›*{ßʯ:Û}ÿÂ+»à&z:9¡í¢»…àÆÑ±Äpƒ‘+›^Çÿ"xó⤘„`Ü™ ÓqÑÿû²t§ Ö&¦ç2Lý~¤•<[¡Æ¿.Ô œÎ^ÇBÜ­Ý5qzsjc-½Šœ‘¾ŽÎX`‰´²·–¡Bµ}xKŒ´Æž`Tjcó.eBC4EÖê?²§ ¨æ¥èlóa¡™K¿a;*qdGEö‚%¦²TKR¿ÅŽŠa®‘'{ûÐð†Ä¹¹äѦUòhhª^º˜\¬ˆöë¸ÄŒ5¼@£ÒÖžú¥OÚ¼5þ<ÇÑ‹¾‡@Ø]q®Gõ–:AŽP 0Ú»…JÕ+©tu¾•& ÁeL­ŽKé(L)þÞþRÑ:ð¡·íùÝçuž$µ€9ú®Ä0Øß'E«ï¤èìÿ±©Ï<…¯§Ðú Á`6­Ý~øÆÝò µ8I+®NÛøîWG…=nÉM£°ZæÌ„)Â~].Ò’À»"û¶$Á¥fH.àŠ2n²'¶™=!"þAg¯D‰ßÓÆ8ú.lUgOš‚‡üt0¼¹©ßJœQ«,E íl}õƒ&C-I'ül! Ýh€Ðéóý½øód$wendstream endobj 6 0 obj 2221 endobj 17 0 obj <> stream xœ•‘ÁjÃ0 †ï~ C\I‘ëº1ƒV|;Œn-…f£t{ÿÙIJ“ãF–ù~é>¬1çÝà6[28\Âc9wv40§Ýw¹Rõ%AÞ»INÐ3ôh»yp¯>5­™…ÄÑß7e cï¿ËÅz“迚¶Š ùŸZ°YJÑ¿OwJ~Wµ’KEX ÉWÚ}Ã$ _ÛWå[~r¢}¨6òG±D‹¾º&Û+ÚÖVÚѤ°ÛÏÕˆ¥Hæ—:]Õt6h&ÿ¼y=Æ%fƒ+· ja×ÿŽÌ\,üoÍÖ–ŸÓ2kH” ÄA“N x-zÈî¥ÄAn\endstream endobj 18 0 obj 259 endobj 23 0 obj <> stream xœíÉr$Å5‚£.>ùÞ7Wt)÷ŸŒ±Ç806 lG€mÓL·¤‘Z âKü¹~¹U¾ÌÊl-3Þ"‚ :õ*óåÛ·âÍ‚ŒtAÜ?ñ¿'ۃï˜\\ÜÅ ø÷âàÍõ‹øŸ“íâ“#€‚ŸTŒ\(¶8:?¯Ó…f MìH¸Ym¾ère­­àÃgK2¡¸ær¸„gª©1Ãn¹‚Gj)“ÃÍ’±v¸:õLs:ÜåÇ,­UzzÑj5¬ÝÖFZ1\]NÐÿ8ú# iïÑK–LŒF@øóƒ£¿þ¶Ôl4DËáÞãfµ °€9¡„Èát¹b‚BëÛðhépìž8œb‡ÝÙ’Ê‘c‡ÃŒK:ìVnf­1jx‰þpì°ƒ 9nˆ @>œååt¢Ã9Úä=_¡ /{§†-a"ÀHÂ¥ ùB@ù«ø,ôðÕÒáB¤•—í:¼J…vˆå“>roŠÑê‚ñF~Œã5z~…ž×ø…Ýú$ŒÈ´kÑF3`­]›³üÜAAßÔÒè~vTÇVýSþ]–7RɸØR[® éõ\:mãÉ€ßJ~'Ùš"ÃÜLxžñû™’¶S…QßEîK›Ù_8lËgÆ&,#D‚ÝY¥«¬•â<܈=Ni˜¹“j¤¯—^‘l!ö·VsetŸõD›íÖ8¹»0K1L­8UèS¡Ó»uéVŒÃO« ™Ç4 Žu,¤¿«ÏbArAs­8.1VXº/¤(nT‡0x»û¥’Î:§²âœ¨þà@a‰¹("EoóbÐVJt0íž`ÅÍ8œn€>Ωq6*®ºNÅ«¥£¦,©FÂ_—l¸ªédÑî²Ä® KÆ8¦â@Ñç篖҅¨ £I\)O;e¬ Ø?ðAC6…i¯SÌBZ¢uÇì î&ßÜE‚µí%Ži6ë]À$Ç ªˆß®Ê¼q÷©ãlït@ùý3qi°Ô`p|§CY² ^Fk›0 qãGeÑ÷iìüv˜Fدlî“)·U`áT R€¦Ÿ÷vSö®9Ådë§xzf™Ü…EtžQ’9×h&%Ã;,ëÉÆ+—ùÊ*0zBh(±nʼ-yºò¼A"Z¸~œ77‚IAç‰kÜ&q×Rá¥ÁG!ºæÊã7?ɼ٭ËíÃU•-N=O*¢K9K‘ ëù^rÛ ‘0!šˆ!zhm{±rÔEÊÕ{K~% $L¥!óòHô¨’4>5YE ·lÕGš;||Gé‚•RLÉWYœ‚DT@6c —£²r ЍM݆U FW›Ž7ËTnÊOÇÏ©G¹"Ô‘—7&ãÉ û0Í[j /+1ɨ VE$séWÎáõœy–1‹àÖØU±ŸC ˜Š5([b´Mò&uî«°……Xc ÞD¼%{¤5S\h]ÈÎ}:Ôbú`êl¯³v€“Eºr‘Þ]ãSlÑUÏ5þÖˆ-.ÌSNuøð×%u‘“,Qß  ¨(ýE?ÂGAMÒ\ä:êÔqŒPé÷²ºj Ž=¨`ªî CVÈù]/›ªŠr—×mˆ‹ZbÃòid˜DÃê=¢1­‡éâ8ÉcYL„˜ÅQœ¹L”VŠçó`ef‘õLwpµÐmfà|^‰ÊÕ«¦à²D‰—¨^·u´jÎr%·¥¥´J::ŠŠC¹øf º†È” ­¨´ÀoOŒÞ“|%‹ðò>,[*öY ¤-ëµµÛpojªÛisŒVr_d@Bî7êcÚ´ÛXÿå‡ñBí"÷ÏÃÞÒ¨"ª+¬Èt¾ ¥šðˈڬ%¢ÌmiŠqbÓb6ѶB«üë·á^eÞ³Ã^ê =—•½Ô›¹%À¡[¬14!f–`r@Ó1Î`Rç`ËêñwRõ© E1&¯ÚúTàãxÞ ŸT£mg./kG¬×H efFx#åÊÌÒBšÂWË’Dªf™™c/3çwöÔè|œÊ ÀÆ=¨"v[µísÕ뙈¸Wjüã\j¼õ¸ÈèN<¥ÎìI §õ-.Õ­g™K|Ž µÚõ¢ü) “>õáSÀhñ˜ m}$õrëd~G ’ÅܳµMuËJõ½ÆwoíØí“ÚŠþ(¾?™—*~“ßcýc-;Q7ëP~€yB_³nñSÀR7ËÓK{g¯è*‘Â…u§S´Á:T5g9ü/b±Úµ'oóE¦"åáç!­PZT…|(¦qBØ ¢ÕO–Ób_Í;ˆOóIî=é¢.²ÀNQ.¸ˆã˜¦•[ù“GXSª{4rø³?R0¢&¾\¡Åßóê˜+dkè¢rñµO&ÃØS–ÀÙ›õ8þ(í/©ï[Vâ±1ˆo–Põt)M'»ëÁçZC#CHmÃ)CHÕ»Úº:W=g²ÙÄœQHìë|LÌc¸ªt’ÍÓÛ˜IWãJ RWç0§!β­ä´P¡ú fÝDZæÀ4ö«>ˆÓ”WEº_äx©áŒý£žò7$ò¿ÍkÇ›V³™ÓQB4^F¼n6—èB@µÕUðK_Ó°¨Þ–ÂKàõH:ùE‚<ˆ)õF)EF÷©ZVO¢T[ôt¯GßçëÞôTòðýpÞ—Epɳ˜ É[Þ×—/Xe £uõ¨¢Ç/˜ ¨g¾ÚéÞlî'ÔuËèÂw‹l§[´éyUÜP.ê1:Öv(9R,ã8O ‘*“M†|·Ìv¤)GŽpähÊòŸ$G_5G·ÇÔR>à6~ÒCRõH>¨|9Ÿ^z¾òQÄø ‰û´â'bTÔ>öª½Èvê‹üøMRCù`C¹AGçS'{¤öÓÑYm¤…»ÈQ±ç’†ŸÏº„ ’·3<4©‹A™§HßN“OØí\ÛoÝê«•™/~Y¶W©OÖÉ{cyœ$àbd\$¸Ý â$ŠV§¸ô^•-qc dÂLØd,Î2nãÛ}¸A ÑúÃݹö¬©c)ô%õÆÈ{Ò‡^9÷´?§=Ó´ëeեʘ»Ÿ|šDH!ã>“1gû”ÞÈRS7(S¤4/½£‘ŸüÑJöB÷ë•Þ0ËŒî1ªÛEÖÒmÖÝã¼úX5æ 1  aın’¸nš†|ìy˜`ÜÌ)ؘ» -|"ãÌÏ®ËÀùœ‹çÔe∠Â'‚œÍ¡½_º²§q·,æÝ6»¸…(F)×»Wi뢻FZscÊUp[ænû”¥n[àÑ·²zâ‰,»Ùâuç¹ìóMGhîDá±C9pwB;Sj—qªX,g\ubãhC5陨PSböqP³¾OðDI’òz醖¬êïÏcþ^¼‹žÖêÃü!‹Û¡UtÅ9w^µ2Ê’ÛÜù̲ÓCœæn7}þ'-ElB¬ÿRíh©E Çu¾J¬' q[±Õ\˜¦˜«ñN,Îý¦í4Jm÷Xá˜]Ûn¶÷ôPgo Â…µÿé Bv:A'€hò(H|™WsÈž’7·ºÊîáK;uÿh&€NÐÿ6ûq>*mH`ff‹?± þð÷jó ã…ɸÁ¤Æ’XX¸ã¼&ð9‚AðÞ–j–ZÎÿ%iD–ÙÛ»¶]aªPÈN™ex‡C,º“'|ÐÛ±žA rˆø€Ä¼cèâéZðäi¤!¬X>D&ÉÄÝŒÝZOÿC`gVx“ißÛµ<$ò°ØËŸ]ýÿ—«§î^Š]}\y¾«‡¬“HóotõçäêŸsrõçÿ5W¯~6®M㊠9¶×nª„(€—­æÈåntÅ÷‚uöÜ(Ñö¢÷åÁ¿:ëendstream endobj 24 0 obj 4283 endobj 31 0 obj <> stream xœÝ<Ûn$·•À>ê+ô¶Ý‹¨¦x'³ ¼›Äqlx¬E°pò Ýz¦[Rfz<™|}ÎáõU¬–ÔÚ] 0Œ)±Yäá¹ßX=v:âñß·»“W¯…8½ùx2žþþ¿9ùë ó3Nã?ow§¿9‡Yð'“ƒšŸž_Ÿ„×Ù©á§ftÃ(ìéùîäç•XŸ9ç'ÅêÇõ8ŒŽiØê<3Ã`« [åäêíú F•sڬޯϸÂùvõS™»÷3˜sF¯.>é䇿œ Ð9wp£c—ƒ•#ÀùÝÉù¿ý¼:ÇÉ‚+ÍÅêw—Î8©W›ë3Áô ”Z}Ä9rG¡VW€´–#ˆøèð8ûÍ}x— ÅVwøª‚Ùê’ _•ùiEåT\ƯèOÁ³xƒ¯*ØS2ºk‚Kº¯_ü~c«ÏágÍ÷kÇqšJ7¿ŠÓ™Zýimø`G£V_Èd Òe\ÏñÕæ.¼hmŸ`üt|½v°‰¨.Ê j»H†"¶Fkyþ+ýqC~øÔÂ.FÎm}b•ça}¦€aíêkœÍ•à /‹ìÉŒ.Žg†I0ùL=HÉóÏ/Ùý†Š3 Én³Ý\To*ÿ½LÛPPn }©È¼pÔ¸¦§¯pV(H–ß^Gˆ.ÉçÛìo#)¹[ío[òùwñxgé|gL JJŽù†ÈLı°²™ Ȳù•ÌTð?Ì38=ÊEîS ¹O1`~Iç ›¢v˜ -nºßV('0\†%…ÖÓa!ÅtžMÚWšF¤2§½-Dïƒÿ+XÆhÐjrÒ±ÚFú¡´5A)0·qŠ‰ê ®ò £«L–”p쟨Ù¨5cB ç+Áq,‚ƒ ‰†c½0Cá’0]EuWéÁRÜڤŜYÔb 6À¤ƒˆë]òÍ‚8D½8(Åa±^J‚êŠ,¸¨º"À5_r t´ølž‚q¿¯Å (Xº‚}\R©)ûÅ) `~¹šŠŽß”<^vØiX»Œ^ÃaƳØd—.#˜* ¸ŒVVcë3ZÌßê‡5þàý¶Å®Kà%= @Ïop”ÿ9¯„î(r:÷³?+•s<2àú î §3‰.^ÝE#1J™µ§u´@r0µRZòJ­Qí¨~iͼlàe/8ø¬­ºƒþ«^ë"m€bµ%„$Æ“ÚÔ»TO* Y@–ö10¿^Ï)Ó]@ˆS³Zm‹Ãðã|Øø¥R¥ï‘‡`ÝxiB*䘊ÙïãBR­ ->%ä>Þ2¯ô¼v³f¹IÚ­²*µXFÉÖ2‡q-¦þV„†@¶Ù~ óÑ P­t]ðTZ«¶ð¯g9~W±'bu„ ÄꡃwªOn:sˆXìvöÅ ]ôtƒ8}¦+ñ¦!xÃeÀ”÷Ù°º’à?Ҁà PùŒz†ôµ Ùp^9Õ•pÍ‹ÝfCÈn-§a¸x¤TE2²J8è>e6™q3Ï…¨N˜ôˆÖØ3¾æÀa‰ï[·'aGx÷K<¬ÐÙc_ã@݈ É ãL 4u”)‡UžÏ:HI8Cm÷ˆÒ¿ïÑh_1W± wj”RCþG5D½ªç <’/Â*nõG¿%¸Ê­6^áiÎñä~w0«ßyæ–|4T?t$®r4ÿÕ ‹æù0`W;fc¿!~ñ6m:¥‰¡Óé%eø¿Ö ”êØHÓö²0h­ÕñQ;™{r>²˜Õž‚‚W ü¼Æ¿.Õ¨æR N ÞâéYõ…êCtêꛢ@.Ö ˆ€Qó/µðá õ+Û“ ttÍÜÛmz=¨:À«HFå퇸§U=*|%­}Åat™¿Åùà`}ÛÆž—K—$ `»ž¡C¥„¨idi$àˆQ54BÅ.aa©R"H·ÞLãöK‰ŠE©DXGñÉG—™E+ŸpÛI‘4,Šk(ôh„ŒÃÜØ{Ê$q]ż[*‘1>puß¶¸Íþ úò˜JºˆÁÄ(*BlHrê*L3<#ÜÍaËì°|¢Ë7'¶à¦[k%ôˆî:’Åb ÇP““w€#ÎßœñÑ‚°6:þÖ “CFVäÃÅ9MÓLÁ2ž’ÓY·„VŸ*Dçˆ,r—ÖtlýdÙOöM Î7‡‡Õœkù„Tž_:Y®©GÓz=@ÄÁËuºo›`vb0ÑÆÂ* xÎqÔH(‚¶Þž0ê§Â`û? »1QE…Ôœ¶É•A}Ë9„“!‰p‡ª7^æÇ¹Ó?,g;tW 0æbõ{BáëplžNÇë§Ífâ4„9M¸Ç¹õ©‹ˆÓ†›k æ¤ñtŸ]/RX‚[D‡+¿×fUÊ©'“2¤‹ü@v¢á w€6Û„+Urc›”–5É£õ ð%iÕäN¼BÔ€©Š ¶“ÿ¯²Qïê wFe×çÎv]*VObO`h$ëØó T ð–XýG½.s7et[¯Êã]™{QFw³s¿Êsg„ÁÙi®èI—Ù:Ý_w5g±¦‘²·kL`ì]û;8n'qJ’õ–ù\6í2­Ï€>÷çôbÈ{s«,5·u¶¶IÀÍèùxRÆøêÏ+¢]+`:iÈ*-±%î1-lüyR|@êÊÇOHÖœÁ¨º†, aqj¯¨¶B:ñ(f>z1V53UÂI,UGDý©)×Üov4C¼ø†ôµ¢*6¹Â“»‘aÒT«A€KM£üI] #sp¨tò»M ö¯’f47@ØvÙW&1Šâ»’‡ø%W"¸©êUqU/ÂI F‹ Õz‚NyL@a©©ñ’í b/Ø  Nöµ0$ÄΚ ä¨Ói¿ñzZb ü¿Ëãë¢é¿£Žaü”G_F(£ßçÑ¥¯x¢B¦{â3ñá¼ m*›_×<û¢¤M’0-“ûó,á½ãëVÚ‚6JK+C%ö8>‡HâOJaœÚMæM¹?€5ÃüÓöíA1³*{éš*&lveû±ÝÔu¼L9?1£O„/Ä6Õ:KGbI^€¨°ÄU‹¹išßœ™³¡©þ¨OAÜj—›óÉy‚±:“#ð8f *æ‡bn~™ U>ÊÕï˜'1ž•  ÄÔñŽyö)g.Wä?†%™d½áU˜!gœý0ù±:¿zÓ»&—ñ<¼_ú¢ƒ|ü6©U;v,cŸ†GÝÿ¶$ “Á•\Šœ¦Ò9d9Y13ç/¥$§çô‹œ¹¢T­AòôÓ´ŒÇ7øhØÅèZ6Œi¸L÷&Ëžl?I2åü¼Ÿbª¬Þ6º— göŒtÁq0–euøHû„¢»+T¯:çËJ[šüÍ ÍÚmSlXûZ[Ón0 Ï8ðWä$W€>|?ŽéD™T›/1hL™äˆÀû•qñ`BS:Mêø·½:Ô´ãÆ¯ ºZ†N]8zé¶ñU/Àv›L^SÛµ¬ö%ýÌGd¡ØË!ÊÉG¤e†ThÂk ÆB”Õ´kòú…m¦ŽTn Ñ£wŒ*ƒ×=m˜ ϧÇÂoÌX) |[åk*mËpÎ|íW\íz ½Ä ªPÂòD'nçY›‚X5ï¡—fÀCVÒàÚƒ¡kÝ>-Å`m/1 ·äŒõH“ý‰• íþôB¿h8kêØ¢ž±29—ŽíÈô¿ã)à=tŒ®Ã‰F5£ }ð(?Ò רy—…'ÐÁ5 Õ&úF˜°¼àPÎø™),oüÌ Zp#=‚6i_ðŒý¢÷3/›eÌã±|^[&êüvÄlê*2nlÛ‹¼ä)úâƒE+à{5¥¾\ãbrŸ?Á9ôu˜ç×IŽõ ±Ä"ªËlƒ‰i×~f â2>-Ùg§f׈ /-Ù—L{§caõ]Y#+éÝn'n@€]8v‹É ±ê)ÚFü®G;Ü×$ª$¡ÝF@±ï¤/Ámr,-] ÃRE/"uI‰:UûªÜ·‹UéžQßñ;É|™TAŸ1qìcœXp]ËUY"âb`ª_ex£ëj O#Ö+‘K§ZoÇßOš¹ÔÓÍÿs„Eäüÿ×¹dûÓ:'ò›GçZðÌ<²=˜%ç3è@tÝ9âÏ®ëY¾²õ’9§Y²Öù¯Džn^*ÚP‘êõÉ=¦ßbKXÏ‹ˆx®qã¦÷}k÷–<Ïô8àðÔÍÞæÀ6»Åë¼\çøÞsˆ%x¤>‰(›¿¼qSF/Êã~í+÷x ˆÌ½/î‚:q6dÿóüäÇ ›ž~>1|<Œ™ÁñÓÝ‰ÒÆbÑ/lO~ÂpdqНBÁ¬4³ðR¤ŸÕ» [ÉH¾‹ýk ¶ùÀF.É’¦†¹ ¦^ÿÝÕäõXì†À—Fž ŸàY |`ÚÅB]¯~BÜ®&Ü£½¸þ$ûÓi„ž)ÆŒKJ±4RQÌJ8›$ƒYz%õlŠàEŒP1z[d„zoUÿç6: |Ò‹‰C^õ^ÓÎÀìX話ò×m2ã$KÏD7ýÛ¹|Kö«îÍG—ÛڜԌ˜Ñ^Xó0Ú›ztʼn¦Æ;iTúT¬ÓCýjÑPÑž;ÎßMvÚ$‡&d¿Ë²ß}%]Vw-f'ɇ‘Üê$efKõxãµ4 ¾_ÚEƒOÈ?pV%J©ô]µ\-–™®EP ]³ˆ¤•ÌÅמ/sªñSï>‰Ú¥n®&S3ÉBy^~ŸM·èN­_´3¨—&û¼Pr¼WÒ –®×H"”Nº 1ãµx%·òv„tQ n(ÜNZûnÊãÕQ’¨8Øap'Þô˜‘Ä lþñ¦<Ø,Rj"µ~ôs%=Œ_å sòdñº¶>^jåËJ­^Z˶Ì}"У±5öšªÕåfPpâÁÇ8Ó¿{YL· “`¶ ³RJc–„êGÿÚ^$ÖzF%ÿ)õã$9E®šÇû»)¶œ*ÊŒêZu.£ú€¦¤¸¶KÊíéòÀ—–{1yøùx ©<üåÿè?¼¬» Ä™ij±vµK½CTŠã{Ï—blÜÝ?¥/éŒäV¢— >õ’üR,_×›·Þ å™ÄVõê [ÝÌ&sQ>LËi_Aè;8Mù ß;†­Þ{TØŠ~S„ðýfÎL**~Ýb¶–T„–*bñZáBÜ‹¬<º:Ó>唌¶Šw–Ñv@ÑS¼·óv6|Ìm—š2ă4ÜÀ´YŽ–?žÏëgOà†ù‚iz)19=ÍN‡¶¸î-ö§V§dÏøiẲïg#¡7½@§¦u³¥~Elж@#Jl|O±#ˆ=êÁ*=MVÑRȾiò툽ï -¹cQ|³õ92ÑÔ^äËÍ%Ké±Çê|«Þ‹ÞOñ}„L>µA1MžrwfˆŠß0Äwëš#{oÛ°™Ü$ü8­…=rÊ é ³9óE øP  ·IH[‚w"‹»´Øþy¶Û¥c?ÝÝ®û¶!¾Ò ‘ðI;0ëøÿî&äÙú‚9`3•ßß £ßW¬KlF”#íH÷‚~téùeÒÓÖè‰$Tµ²õ|;1ÁUGù—½[òVÄ4JÎbú÷?‚˜”&0þ‘•Šžý?âû¦´5yös£}nÉraeæzÒ# +^“/Þ ñ*†;@¼ìE©·ø §ç¾YàÖ|”ŠU®«á …•ÓRyK#OæTkCóSr`:ŠÒ÷…ð”#÷íI´ØhgŠïñëz8E‡V±ëð F£ÿð cMÃ)~¦GrY]ñ‹q\x ¿NÜmÂì¸ øeT¿ŒfïNwn•´Ÿs0Ì%s±ç£Ž^AaßUb‹I4¼h¿d1пÂÏðáå óÐiTc_k’'££mº«N+üÐh¶Û“¯TeaA§Dš|£ò­°•³æµ2Mîù,™€Î\Ú¥ï´â›x¬Ý½ßstbŽkxÝMÔiG¡ VÝÏÇV·ª¾DYý¦,à^t¥ÄoÊ€èråxþsYn~Ì •[ü0¡3Hs¡¡x?"Ñ#-ü›ønýw²ìhFQ<ªðÊj¿(üúÕ+$‹Ùtáfy~®Pþî“ï$Ò ÏˆLÉ\ì5ᣲ1Ç%‘-b#ˆöŸ`ŠÏˆoxͰx{7|.(Z0>ªªöy[¦ß—-1ðR;l8yÅËøØ>ú-U}†G ç"コ)ÏŸÊŒ+WÁ·_gsl¤cˆ"ì€ œû:æe*Z%*Ãû 2%¾?h-Q8.xøÚâg©@Y x…ßM  èûçã0—Èkxn Š. Š(9÷ñºa &ðãô½==Sùèáû3°phWNÏ w6ºôÙ±ÿ'Ž=Ÿ“xîú[}wßÎð1wåÅ‹ÂÚÛ'²> stream xœÕ\[ÇuüÈ—ü…}0™@ÓéºWÅA€8¢9’KkŠ»¤ÆšÙ•¸CÑü÷9§.]§n½½$ Ø ˆ­í­®Ë©sùÎ¥úÇ«ybW3þ‹?_žŸýó×Â]½~x6_ýþ¿~öã3æ{\Å/ÏW¿¼†^LnvìêúÕ³ð6»2üÊÌnš…½º>?ûãîòÝ~žf錓zw»?p5OZèÝùž<¿ m.Ã|'Ãøî%R^¹Í£±/GÊ wµH„N'$aä¤a›&&%¥  \WX¹¶ïˆèÞv-t°T 5H:CA³äZ^¸n³œâœäÏØ–J‘¡´ÿë #3<ï ƒ)Þ½¼èO;Ö" sßÄ™¬Ù_d‰i4@žf‘¸)î…·«èù÷=i€?Áä6qÜO™ï™Ùÿ´ËYnþi¿´;¼,8è]G¹¿þó3¿^«Uà%E˜ô‹°úYzõ}à ÙP®ˆþô„T³P²$ê±fÑçð’¶»Ë}lÝ!LÀÍŽ>½'\¾ßƒzáqÐÙÍ…ß—lƒCkiŠs* Üé”-íÄM>J¢oâžK.ù¶Xžg{'¶÷]?Ã)X¨Øýaoødg£ŠÓ¥-³éÂú]ÂsËdñ*¥ïÛDSµû3•£óé9Ââ°_ÈöA¿‡·m<¶…þ1Z¤›âÝCµè3dB¡A‡òÄΤoÚ6¨€F,£º»^Yž÷`MÅúJÑ]5QaA*•­´é?zq“B)?@læ§!„kn]¢2ŠÓ“ýI´æeþc4A;¡æ±8ŒßVhÁ³’i>Obèm]©| ‡`¶ãÏØaí\7å,a˜€g¹ô¸›áô}V篢#¢ul(z3Àá}_8zâ \ë-¬ž‡àIŒçÌß3ñ¿fZá‚(ók\ƒHî>)¸uÅ™sÛDöý4¼4ä™7à‹;UÚŸD-ïÄ]û6W`³“vrƒ×¾þ%yØÌ~ @ CØa °!¡‡t®Âv^@Mñ8ª 7ËÂO K'Œñ]ŸÑÞ@‰–i¼[„Ç ¤èÌPô7Ø"‡¢>Ï/ªSXň'ééPæ?]²a-"|„ûÉðµï}8É&­T6O¹ÃÄé/‘[aí‹ÃF¨=_169¥¢GÇÕUYà:3pbŽ«•Uàõ‹=èA îÉÝó›ÀÊβ}D„qþ6¿A ÉÓ;Ò9êcÅîk/ìÔê©(ôÚ}w-ç£QèôñÕY°~CÚþ$8L z x®Žé«ë/Ÿ]ÿÓw¿õ/a-;4§^èð8'eØî—{ÄÔNT*CY¡[g<¼÷j¾&L7o‰?]s lrSœB€ûÊ,þ!´5,•ˆ< ÚPÖüe;*\#%] îsfÎ oÏ•j.ìÕ)ïÃ2‘ºãJ±_¨ÑbÎÇQ4±ôÒqR~o±ñSi)q&©Ä#ñÏä·.û¨=;|Žñ0à/ª üB³ÄþBV¤žRe†Â€J ‡}ÈOäÌ‘£¬Â9áqÛMoöC2q§eHæçû%ó<7?ÏÍ/róz¿8êÿž:XÃ×ËÓŽð‚±œ%“E8+ò E`)GX 4Ö,&#pLôÎgƨ,á òü[*ãDËO‘`[D‰¥": =”r\€˜7 'K9…MØx–èŬõCèÁ8¯,þÒ£Š!AgUhÕ"]PyØ3Ë‘A%¤x™‰;š¶iR °Ð§÷Avg&§—lò€÷0;Õƒ*SrKÿmˆ²„Sp«E8‚dz R\¤*‚º M& ™&%ÁôÊ(ˆ*æÒÆ m0½tYoç^“6ž)@)Æaª7 ¨UM ±¤ö~žåûy–ïÏóÓ/òÓÑ $r¶E(¥‹•a3bOôŒh å)±hï¥)“¦ Ñfbü)ïᘟžs3÷}4=ô¦‡ê©5¦þuoêÛ<5™ïEn¾Ì͇ÜwuA-}0©prìr­ŽûÌï¬þ.¯èEýÔ7ïkXƒ_*»Þ¢`àg@6%Õ¼ô¿ ¬.„XMí@,( Š€ZbÔ  5ú¬÷±­; U’v†µ' ïm+¿°I»É”¨¾¥Ðœ>®­L3Ë­(Ãç ˜‰µð2RYÅoê$…röÓº›¾KëÛ,5ºsºôhü2˜žœhÐMŒâ2ð¼¥nÏ0΀gÈ0¥àF¡‘iÓ…†±Öþ¨ ©ø8ÇóÀÊœŠti|9æ‚°9/ÐJ;gbÎÕNR–jà%™Ñ“ì6®r¶Ý:ðçÞa͈³JÉQŸ]\ÉúàºY¹ã¥Ÿ2çËvû²QÕt²rq…kâéÖ¶E!þäTL˜¿¥ÄEéxt"}›ó ¤§y–&ˆ†KQ™W gÀu¿KÇ.2/å„w ÷ ‹úˆç“VPÀ©ÙF!:pEU²Ü¸šÞüÓ˜âMJ_'êz9P—3àÀ2ñEC“–½Y]Ì÷œÂEp ÌkQ@¿Adt«Wˆ³ P¹µWèÇÇ ì1ÕKT^øŠ¿ênjξ}Ž(=Bzò'lYxj[;æû(åµuùD ¹š£Á‡uKm)j$Ÿ;Ž,‘-1܇—Á°j#’ÐÞwÎ #)±î6<˜RŒ,ÙK–qp1ÚƒØQøDF÷ŠEO`Ž©Öè;½= wÜzi^„h.Sª¨â ò!äw1ÜkÍX¹À…a0˜|¡ïÒÈÀ‰Fmc˜™É5w:˜y«;ç+´6Ô<¶. ƒcÐrv`šÌÐNë/ãr½ýæ˜9ÒYoÙpÃC~&5JGÓ(ÒËfw‹6÷År·|"…]‰Ñ^ð0œ^ŒaMGhJ&?Õó[@F¶tlb†—1]àÒûØ=â•øæ¹X—/Þ* ¡¢ïÖZÖ¯õ«;2úTë0ÎÇúuk@‚¼51‘~I© &+›\qv¬ª‹ˆ4z_L¸+ò(iRïr"n!1°ËV.ªò«Œ¾Éé×k‰ƒ·¢”Ëe‰e<*°æÛþ#`Ú'}*¥UÀö^ÑqTR©èØøÒøðÌTè°ÆEËÀ=šäi©JÔè jy|`ÕÛãb’š»2^“yÖ€áˆm8YÍ[ʸ©J«q N)œ(sxZ!ö2'[V†´þÈ(x‰–´X\Ï·ßÚ»äÏ0<Ÿ=Y߆A½H-G‡&ö™4¿§–à}" lQ¶ÿƒå#”}Èîu´ó\Œ >Ÿ‹ÍÛ¯7ºÕλ[àvM–y ª¤‰›(Ý”?l@ûv(( @^)kOŠðþ*âËà#ãfQÐù¨š«ßg4ëO åQ©'ȼ`í0]µÕXÞýE_: ú–¬#çíÒÑÒœHGAóí*Úº@s ?¨mõ] µµëÈRÕu`铼OdymxÃò=h¿Êò¾ˆP¯”û~•›«å¾h6µr~‚OæüP¿¢Cˆ1´§âAßÕ€Äã Þò|z¡æùTêò×´5ÉPÅR@9Bóëšæ#mÃÁ7rK”úÔpîr¢(½ßoUzÃeœ(´Gœg PF~†‘¶w` >Œ6kN:öf»Þ /¸O¦÷Âò™« »;_¯=j‹XŸ£eÿ~ƉB}Zªâ}+'e0GÂ'”H—@ ¬ÿ PU¨¼87—x¼® â(l|…axc%Ä>›œ‡öÃijþc³ þ/z$¶\.óHD‚TJ©*HÁÇ‘z´–åuâp¾–×ã€èµd«NŽ"¢omV$ר–»¯¡éŧöƒ` QË…CQŒ¦—mùqi{Q@c¼k°röÀŒÃçÃLXä:×ê>¿Fzßì+us»ê2¬ÏÿÔ‚ƒ§nºHý`äRÚ‚n‘ùÓÄÕu`×È܈­ÓžU›ÛÆÉÍð‚ÐFpáÅ Ë»FÁ½D-àsš¦‹qа³É°û…´ßŒÓ¹¸óÓ‰0ÓÜ“ŠõŠm–§¾xMi@ÛÝŽ¢{a‡ìÚRÄ¢ùX¿È¶ô·¹ùâ~™›¿ÏM’·¾|¥Å*„E5žŽmÜ%ÝBê¨pÍe ¤l»c«q|(½“¼°ÀÝ¢L)?Z´p%†kÍRøð—fd4e'£:Y鬅‹¦Yô®Ë<’Ñ=Rá=h²Žü´ 4Ž¢êëdãÇQzñMÜ(¦jœã·'óäç2r3^*áEX©ZÁcž83ß”îÔÀ\ù¾ü_á–ÚÑV·Ô> µ u…{e²üÆ@S6¨ç†^pLˆ6:©3¬(¨µT`Òª ÆyöK<ØJ-S».=¶ôn˜)°nF¢ºñ°7…¼ 1 kËåÁ$<…“AW ODªöò<>ÏW»ý6Gߺ jФG]ŽuÜg’S,ürÖºER~.á"ë p]cÑJÎ:~[³¡ØÝ2;3„+ÐX˸ÐÎýËãaÕªMá‘bÑ5ÁêMb´ãy4 Œƒn.$š¬”ÛҢ˪¾A(•˜ôŒ¸QÔ¢ úÊã´‚Ù¢¤r­üjMÍU©ŽÓuE»jfP®ŽÕvËÊͪwªù?À¬Æâ¡i0-½¹P(¼ÜÓ“åøÆn©¦ŸÝ(ÎÌ—»3PL`ÜKt,’¨·i"º¿¸Ý®_|fƒöj2%¸+Å?¥:ZˆoU…£âwfUñûƒ—­…Äçþî{R"bAµ[?mA´ˆ§«Êl¢:ß‚ˆ‚û­¤yÔ˜Z†þQeLiT ]2·’Z¹åêá–l¾xõ4„[;ßÁ«û‘j¿ÒS¹`!+£¤›Êh,+ùºrÁ2~¶^J5ðcKxI0¥W ¤bö’Ÿ’*à7ùé*¦š*P½"ž»´ìlðD°`< ðô÷ñÍGaÒ[(±’á­»X (Ž×VdNmÌøâ†ûØŒ/ÎÈ)ÚÒ¿Xúã;à%›&ù R#d+@Q¹<ärîH}lœ…VøãÓÌx•(.·D)j\Y)ï~n *õ½”P„ ÉDEÚ¥ªžòßuë|z.ê¡në”똩¿üÞ)Cóãt<guIð4Ÿþ@—ÒÉ«pã|çøí-"…LW·TzÍ ­éÂ_õ#Í7Ñ’å‰Õ#"T!ií¯™¬U†ê †¥±+_'›W+M0éi;©$¢PK%IÐÃ,¢üîgß…Þs‡÷4÷•ŽÒèZ´7ÃøZ…X.Át Ö Ö†c²íª:x7Õý©Ç§ºDRÊ_¨£tm˰q_à©y÷øÄ$L:ͪ.Ï;ŒsøB8?ºÒ•²ñåHF>4Šï*Õ×,è÷pªJ¬¤l>Ut¤w+œ#°³énôà6¸Ì·Á·÷Ÿ¬ð§w+ü%>Ž·²¿*J‚+ó7tÿ{[-<’H–®ê(£Ú«:m ù!Œ¡´.Óáð”OFsútó§ýr7šÛŽ«µ¢sE{a?¯Ö²¸YI1ôàÎŒLwóY´vjnFÀUùíŠã¹v:qÉV}t(¾Hn#½•Ûý8P6Gb«ò1o©à¸ý}]¬³v»ÿ¡êt°ÊXÏñi2dÛÝ` ,‘™^i×¾i9h°UÓÔ»93ûKQÃX<“õ¯z¾»5À[®GvZI¥çç¥ï”cÊŽOøYÚn¼"Ú¯BcÌÁ¯¼.¾Ä:G­—*üê6‘Å".ƒo1Ì/ ÒyÅÕ#‹®ç1ŒMéº÷‡’)ÃFü'8·¤'†ÿü“o ç¶ïÅËD»—ÅêVÜ/Ìè]‚=øÜ~GW&AaϦ—YOg³ñà ~yŽWŸëõ¢Ê¼C–dç2Šêÿï§çÉùmltóžto¾o“o§ÌÜ_ÂD†)¹?üÓ›Ý1¶©?½H" ^‘ø¹Ù÷6wh’Zþéö¤Vü*.Ðc•6zL¿ÿˆÒ_ˆ±&W jÃÒu#6|Dðƒ>ôE?#AýÐ~ßnDú ÞS ™¡’öm|“鲊ãÜ$"#” £t_`¹ƒ¤«8³Ÿp/#Ñ6îߤ`W‰Ù,¶­Ê>ϯŸýþý?oÊAìendstream endobj 38 0 obj 5318 endobj 43 0 obj <> stream xœÍ\YoGvæQ/ù ļ̽ٮ}ñ›gâ8ÈLGçA)鯗¢L^ÙV~ÇüàœSKש­y)ÚH@j«k;Ûw–ê.ØÂ/þ¤ÿ_Þ<ûôk¥/^ß?c‚¯ŸýðŒ‡é¿—7¿½„…–Å3Ï/ž¿z_çÎ-Òp{a™_˜tÏožým÷{¶0å­W濞ÿ3¼ë«WñÑ:xýùt¾Š…Ô|w·¿d‹ðÞ9³»ÅvͤV|÷n)”_œ­©÷«½P‹ÒVÃSø»Rº–/à™+ï•ܽ Î µû~Üã5i¾†ñ4[`c©GxñgñRï$éüŽ,ôf7\ÖeÞò¥à‹ŽÇ?ê˜~Âu%˜…Õ­Kº"s¿­6°v¹Ç3UŒi¯«îdcâv­ä;NaãÞ7—„J´?'ý?“ä–Žóê”oS3SUsÇ©=’ÐZ¦ÓöÙhïy_íúM5gC¸Šˆ0¼ÜèA’…=LYî?†²¿‡Îöbëí’§{¼J´Ö¦+º\Çíì/èá¾!dÉü¬ÌNLÈþ¥©Îô2 ¯q½0Æw?“ÆSZ¦q»?âê+âJ&€•w‡s„ÅÚ8RKVò©JÊÃÙš´WûV^C½ëšÃé¾%Ñ¿Ùu!ú&(Šªzhžá±ÓÍ_f”g¤Ýýðw‚ Žç§G˜hlvß-bØTëŽOƒ (Jº2 eÞo÷å—_‹jÿ_Ùµ9뤙:Á˜ñaë8ì`਎|[,HÇǃg[¸á’ŒÞuIÏÔÎÑ>D~†—Â.Âx ”Ævi÷eœ€)ЮO¤ ”÷ô¯vòž´ßaw z Žç`ôÜsµ$ IxŠoÁöf¬Bm"!8µ. fN‡æ¬q|¥«— Ár#wßÕX ›%lì}5܃¬MF×~¢ËºŒóÉþR ¼æwßì­X³5×5F5î'œ¥¥€Ã8Ó™ÂùnnÈÒèL‡˜œ®ËóñC>t`[wŒŸÇH'æv§7ÁFJ-aUÖ ¡ƒZ¸ÓÕ.ÂpZp8t[uÄNw‰-½ÓÇÖúÅ0‘0<@z'µÛYÇ‚µxtb1Và&FóÙÉ;»äpÌZúÊ'ÒpȤ¦¬´Ý1ñžtª ?‡Ü‘œx÷tÑð‡c&[n9¾ÈÂèÀ  ëãj•J«ýCpï' Ö‘i ¿Ç° wÕYhwÒì~hUFzù@8ìû<ŒŸMûw¬Œ*”†·¡ÿLÈòÊ`ªyu6ú}RßD*©@±W{ ³ÁËàè_¡Ä''¤«¸ê.¾>ßî¯ENÿÌÏóaéÝeaFVbЇ‡ÚS/s 9К'¤_ ðo§»˜©œÃ*KŸÄ3qÌÁ+¾µb€û¸$ j÷uK¨^`ké^iO´Ëñð?¥Oãê„•X¹1ûÕÛ#*ã4c{Òç¸Oòî@o™FÞ/º# ²OwL-äCnû, 0°(ÜrÙ±= –€ã Âõ†:IÝñ*«5µHwzJ‡d8 îlÔX¼2stÖ›Ò%-Kµ‚±ÎNã#µ¥B9Ï,24‚ú™Çz‘ÐE­RUеõ‚u4pqÇkÁömuFqK­(%{-šH‡{‚tD¿KêøØ›â+À»„Î6룪0"×# ‡à>¿6Ñ£ 9GÑwƒ /× ÓÜ¡õª´^­­ƒI Öٻъ¨N~À6¦ƒ]êØÄìþ¬-kPæ]TøBcP:x/ê0Ñý7$Äw¬<:ŸK^”¼vê~ЧìÄ7=Þ•GИ†1 ‰?òHá5†Qì~;ìp(­oKëÛÒz]ZïÒ`G*ȧðhè¸7yb™ ­×ík¡õ5}m}ü®ô½-­wåñ>Ma<ø¶¼vÓ¶¶#Ü §ø)Žë}>ÔÐzÊ0Á•O­ï†³ýv}0r&û¿<{þë±@PÔ†D,ÎŒŸùÖzŽI…ëøž²k6ÕÔØ—;ûhŸ,ëuµ*Æ(]éäiCØNånßÌP5DÑø3Îã‚Å‚Z~Êèó,‚[ìÿ|Õ{D½šÍñˆ@Ë7àñèãÙ{œ}}±Rá‡ûø ç¶áÕ¦öl4¬6B{ðLÖ¨+N¯³Rƒ±¨RK^-xîÜV¾Äá8q ’o÷D#§Õã3ß¡³Ôcs™6W»Æ/Šú÷ÈÿÎ.P‹èi^Åg gÝy#Ø]ÀÊ#EÀ+â‰h©¼³V®ø…òÙÚ83E_¤Ï¯ˆ¤¼'6)Ð&eüñ£a`jÁк|IÉ'«~^8YñTèO–ϨߩM¤y2g£°Þ) béùn°r`âIhŠ„å¨ßJX>¯ƒ5QmÒey=:\q¯>5LW Z:ˆÀÒ(ÙÀµ¢v"pèç„S©µª±Ö¶ÅZG¤&™(MGšà’»'øäô`bÞ%õOàœs{ž7‹à¢w“.9‚–…µÃöš0w<‹> $fÍ¡üù•!gzb#È"b×GMrÔ6'hƨ¸„E•iÍA5?Ü­nÅ‹4“S¥í$¾41)9ñÏíGq3?p"DKFùì\¯uDùy§—å"%é°vKàBïÁpF;í<æ¿9Cp©BÈ—iÁ ¼aFïP#¤Ô } š éוÎÉU´.™ž8#í‘’ýTòW$e<+°Ø7° èwØmšÏJD0a>Ž^HÍY§ò|h_¾Žv¼îðÃcòÐ ýoÏZKõ«£\‘gúj 7–ž×¥Ÿ@kÏM†Ö¸”=Oò„ýó£,Eua5~žžŠIlÝ)¨T4q=|¯òô ëÒEѨ`•£ ¡¥IžˆˆëÄ·˜ã>Ÿš'p¸[n^b ‚1ŸÚ„ÓfŽSW™äz­>’U×F@/’£-õZc¦è£âR‹pzTZö»½Mh­Ý­)¡*–Dt:B:Îë’ã0NWµOu!C˜Sx>µàgØÕ) éÊ»š(ð ØÈÌO¿Û¯±ƒÿܯ…Ò:Òuà­ë‚Z»ì2lXç f<ñŠÓ![ MY¦A„y*j_ßý  ­Æ4]ƒÅÓçvìg 芲$¥‰üÎÖ¸]× üÆÖàã×…F_„G'¬Øýym}˜\mT8b0€ÇÎGÕ)áEžkG£ÚÃ¥b˜ýÓ œEÊGîÈs‹5m+RQ¬#˜ñT1­‚ûƇèÁo¨29’þŸ`!€µ¬¶ÄFQnÄÁvæŸÊÚaßJE²á‚åÔ9¥ìy¨M#¾©™©\è¡sÜŽ‰BÚ­ÑÂ0Çñ@gÿ®¨©¾.4h¸Ù4à›\ØÝóx/ÔŠ•“gf(ú Mol¬©Íû~¥DYv’èÑøcßâ}Q§dÎÒvê|fTê¬>¯–7e—“å›pÊyãΈS8f1FèÚVå“R8Oi) ”ªqõ_Uÿ4Ž$SyMvx“9ßê–ç{ë³FX¥å4cÞ̺«P¤zd~góaDç\ŸàÍ›´^Û˰š_PšÒÁÔÑŒîBÁš2†ÙÑQª·ù=@Ðù0´;Ú'bÝÛ Ù£¶fñÉÿ{Æß§´iôoCà€yYEëù}©Kcˆi]Z` 7CÖ]°'‚Ûþ˜!';ë Kn¦eª¸øD]u©acÓ&S½BJÎND¯|z:„ ƒEž[vN “ÀW*y!F¨4R={´^TÏ»3U… JÄó,è…cq^\ 6j¼ƒ·¸].«@Uwé¢7Ø­g•ÎìE>àir,O>Nx { ’ÿ¢œÖŸ÷[H@6sshÖfU¬lÃ%÷•iýþŒÍ¶Î/¼hÀž©FpÔÒ¿PØ9¸Ì¸¿â¼`Ž)ÄEû &#sNò`wä7cïNÓç±ôZi°º¶1p-ÍUa¤)f¾B<Èž‹žC¢ Q«v8ÕJ ‘,)ȇ³3 oi#Fª|Vè£yS¯&H÷¶W#Pƒº9ë†Ë½ôâñ€©Äó§’åù7´2sPÌ×yM,*ÐG’^0RU¼žŽÙ•G–|˜æt³ÌõU'¥¸Ai&Øo!!½’LÂÁ›Ë“ÔSàR`_’Í嘗è‘°B9Gï­S/K ’ŸâRhÐ oóªÙ¨Å à]°˜Ãàd@⦟UPÅŒ^ì ß™h¶Ž{¢yLRyÌj°rLGu²„Ã[ׇža¹jZ”pÊYtà©’¬åvº …~wXWƒCÏÕ†ÁÅEpjˆmï]e6ªE6j…š–ƒÃ- ÔÌEɳДê`ªÑ»²äVåbE <Ù?•û×ýH"Šøóòø¼tø²´þkiýË–¦¾T\#k (MîRw¶õgËs.ÃËS4ýy1”‰kC6-Î#ÌsLþ2´vœ¡Ä$u;U«]нb“˜­¬eRQ’cÉÚXb˪;é}-ܱ´’J¶R|6+‡,ãN¶•Ò‡5åJu-™»”b¦u†Ö­uNøNa!´ƒuÖÖ9åoÔ4¼–Øm§w҈ŒŽ(“»Æ%<@jNÎ1uN\«´Ò‹~WWÝ{CSr9ÝCv¶Ðò…tyP/¼Á¯ÍÝAa1P¸SC«m…pÛ‹-ÖYÒý¨ÔýÌ v7:ã™^w8ÛLÂ0’¹>^Vf,ꜚJ’ɬxËÈ0ÐŽt§U¸ä”ÉM1é£S)÷i«€T*,Ü„f„3àYleE·"XÝod©¾*úá‘î¿À!¬"¹,ÆÂêºZHÜ™`hG1Ëú¼ˆE)ÎÑ7ߦÃ×…ô¢×}j…úÔn¥ ±ÀRžàΚ7Z绊°Iž½–ŒÕ7e7UVÍËÂÜ‚v Ÿq˜Ý†¤ÕÔ3ÞÛ*#ßògòóøVæ1_ïÑ."ƒù—7ÊÅ©‚ëÙ¨€÷ ž&¢Á;gntAjUÃßìy¼„HQ;)­Ôo#Í*Ÿa<Ã-øýÉ}ÑAռ䎑/ ñ˜ÌÝXïˆÒùA –f§7Ç©º ÓŽVLÕq(“Á!åà*+îDòAJž"¿îžÆHñ  Pº'õŒXß$¤‘îMvxÉü€Ó%¾W9DÚÓÉ1'6kö¡‹Æ{ãç{ˆ}´oĆ ¿ýqJi%è>öT;ü-jqbofã‹ÐE.ÆW…×­ö„A¬Ÿßÿë– ý·ók yLkg…¯7Ôoe!¨‚8­‰Ê¡÷lnhÅÉUܶef–ä©>‘C.-õêgµõb&É¢êvE‰<} …ÂW\¤@Yšh]˜Üœ£û¨.žÇ /¾ù£R­?¥âé0É/ |¿‹ó€xb´KúEàw ¨yÏ.UE­u7ÂÖÝe³¼ÕÚþ¼ š+Ü+{_OëãÃ)d b&Šé¯‰§b¯ÑwV8HVóݰäoQ~UuY£¯D5çùÕ!\ïGOtöiR œî¬R`SJÿc/ b“ªÌ7Æ‚ÑaäæZÛ*ÁÇÊÜXY|MJjSe®Ò&£\‘gº€;òL*†ìƒõ¸ëаӡ½³Ã˜N{nÚ† _àú‘*¢ë3•ßÚj9ô0O.3¨rY°vaL˜†‰8ëŠÞÐWq2º%²ú`EÁHÇ´K›®…u÷5tñàį’âÈnJ nAU3’°E^¶SO(°º¨ ØŒ¹¨ärçv!%Gÿk!˜¥´—O…û¡ñ¨«pï1¶Zö‹ÝÉ) ¥ž»¶ ¤F»Ðø®T»#å¤z/3Ü*©Ðní(î¿Õ@ž W´×µo:Σ]d~ì.©E6™Y„]Ñ÷±°BŒf†Ìæ}i½/­ßî ñÒãÛý)ŒWˆa1n…Шô7Ùª0K·Òu¨ƒ­¾ï'$ åeÁö¥÷&›:Åñ«RáÑ(¿íÃàN4Ǻ-Z±/ƒŒŸ“JñMÍÓë®§svI“¡†ãWM¨'à`Ï«uC*ˆþCñ¼kHØ|))¼*}NK´ô&w˜,j§ÑTV~ŸvÄ3÷pñ³ˆâ À%4Ÿ\°“é§£ÌbÜ}EË× ·ƒµ…È®Q‹3žpÍËsq 0 8ŽÓ TH:µ¡|¤ÁÔ¶Š—8š´ið•ì~–LI¸›(™ï3×TeÏÔë¨"Dcù«WÒ„Ïbr/IÐ2ÓNïA÷Ÿ|òï>ƒõÿ›ðF‹òѾ5Þû+ÛJA‡O‰ËY¬èp\ó[ó»ý—VÒA_ }‘v;àì?œËÙu¬n–CÛ°«1F®ç?’³o¦ ó&SÈO"GÂÿT_­ˆ5˜gUÒÏTT$ßÊp’)žŸ=~Bý&R×q '‹Ÿp¨±UM­¿xþìßàçB4\endstream endobj 44 0 obj 5464 endobj 49 0 obj <> stream xœµì|òÿâχ³/Ÿ+v~óp6ÿßœýxÆpÄyüñâpþÛ ¿26:£/^ž…éìÜðs3¹qöüâpö·Al´`†Ùa„椕UÖ f³eÓ4BÜlá'wvRõo3=‰É—iæý†™ÑZ͆dÀ+2qƒ9ãÂòá–tßl¶\Ân$^n¸ü7ÜQÀ[®`Wvxî7§ødä² @†BÓRqÞ[ä*´­±2NU~óÀ0¾Í'É™ü¯‹ì9@çè&‡Èã¾iÎ/~vñþ¼1|´“Qÿ)錓:@` WÜŒ-`IZËå°ßßm¸-3vøÉws çñKÃæF ;Šð¸P “š„ܼ C`üp¼KmÜ´„ÇɲNXÒ9)²M½Hݯâþ˜´ûƒ;·–ŒË߇!ÆÈ`VÆeÈawKÆ_‘öuµœû@z2 ÇW‚ëaw|•¦Ü3‘#ßJ Þ‹+ Øoý%s 0O™¾)ŒÓÃ7Koëú…S3„wx cSû·íÌ›6€z²Q:õoıáº|_¤6"èÜøÛÁÑL5®Á÷äršâ̲t}"ÀÎ e†#ž]Î i›­’r”ZÿéÇOJƲ¥®ÓR>i·î †B-Xþ<]Ηشp˜z¿§Dêù>Ž—itÛLJ¹•€ø°ç[&F¥„ À‚)fޱ_Ø…Î')úµAJ æFÏ·—¡9¹á»¡¼œŠûâƒ$^ðgÑ"¿šßî§`vǧ^£Aú¼Û0 c»p%6¿Ûø…Pw ƒ}3#Jôûœðün ãóDeïÉà7¹¨ÈI'À '£í3·e2dý,ɇ—D‚¯ë-r‘3æõ|CîÿeëžÄ€F€Pg2½ «:â!Œ°p°ïÛR†pÜm$6ÇòÞ’fkú'@iû €'ô¨4_?ùÓù)ÐpbFÃ?&~¿Oü~z©ù6 ¸O½·©÷7kbb+ae-Dàp©DØAx®˜¶ίj¥¸+Là`*ŠS ½ÛïJwOÉ·Í÷pA8\BKÚĽd*Uã4åDz #ªú,)Ø5íV²+Ú«§=pÆMó”Ê•{oI æé)¡‚TX†-è+zm5Z:¬Û"`1°™\®°Ð°¸MD™z[ ‹ÃßÀ0$ ï×ò½©P‰&m¾ÖÃjƘtæa!»Ü. Ë—šSLR­g¶Ez8Â×Á†Öž2YDÏI¸ 51šµ¢PÄwD±¾ æ=Çs '`§t… ý¢žO2k†ËMã#^ØEÁýXH9ùCèu“,Ä5vÃÆ;lO!“„8÷ûLFãá ô?Å+Æê\ì"ÕYûz_¤æoÖhYpP÷Ò¸põ?œm™ð÷YÐÊxƒ@£ˆ™\ð6¯ç+´-ËØÚòˆÎ>¿ZDrµ¦¾ãÄZû!Æ×-8÷6Þ½6Ùª2B'²ñýLgnØ=„[ a#H„s G"JWÚF†Põr‡…e3·à¸£t¹'6¢}²ð[ðWÿ=i2Ê|G‚±¯¼Ñ!À)0ÁÝŸ‘tW";rQÎõZ®µ75¸b£·òXë \(¿1(¢‘¨ÉÙÈ TÅG*ûçöýVŽSåv³œàg·ïê5ñÓ8eâšõ¡ú÷ç°inrãõmºËZRÄ{]1óá1sRY©<6ÕG9–‹›Šø™ãËÎ=UqÇaœNfïIgÀM)Y:#‹¾ù±” ±½ë›æP* H·9˜\âé@ßÑ-’HÛÊàK,VîgY¹‡ÔܥĠ¸Zzƒ· 63¦±[$ÁŽS±ùÙÒlÈoð4·‹5óEQlÑ.Èÿc;¢£^-Š¢†ŠÚµyÌ%0—àœV$= ýa ØkA¨¥?² íò¹×§ÒŒ>ú·»°%ؽ»C& ‘à7°BÿÝç©^ÒC1ªaºD¦sö"{9ÌCï§ulô¸þ‹x Ð3 yš@ä) w:ÊS8†…½\ÎÛÒ]5s vaîU »ëõ›ÉÂ23r ¼ÚjùÃnT×f)ñƞȭqSƒÉiàO“Œ6§™¬ŠVJîp]M>©²(к»Õâ ဠF û}¿Ö´\ØL0‘K…mOžT ¨©Z:º¨Ü\Ä–·PTëŠüÌß_FÝÁ³åk&‚~¶‹à`ôùß;*«î’ò,Ä»¨Rüý#Ýd‹ªÉFªLžp;ÛS”‰M)“ÿØø’…˜Ê6φÐ4ÊœâÌþn“r$ BS´M0t¶Ok0=ë™÷=‡©a¿Ëü§àç+SêMßkµÉsŠ€¿Þxúf#–<5¯¿'T½£ªÞR7ŽýB[8o~}`·Òyó‡ã6§«@n³Ô#”qÁq—#«|J8ñ6Q59Z3 âs²ªø§dY¬†* ó]{ ·'‡¿g}›\½M'$˜·q€ì9j»cáì©‘7 2öQx^ ^vi¨iïIæÛ,Æ’9·šÅ¨1í þ•l{fS‡¯Êì$BÓ!²v°8ؘ>á;•6ænžBõ ª i›Š`z/Ô¼šu€X3Bø‡u͡٨rVõ¼ýNÂ%÷õ £Ê &[ÃÇM›DMÈx¿K”qL½÷©¹OÍmûûԻʯ ŒkóÐbT©MG±|Bpt6ùÁKíéèLÓ¹$,Ac7!À»jtËœõ‘ ó-w!¡~Õ¯@pI>#z± NÙlˆ,u‹B=Dª2,+] ª˜Ž&@Â#&—UÜàîíª]Zœªð¨e êÑâYÚÊ,³H[W+3°"‹tDy8SÅð3 W²±7C”«Écxáë JVcLž¤ û5¶¶&ì¨Ï’ò[ó0kNÕvÇEºX‘˜{Çóènúàô¬Š÷nU¢h†ð"ÿNo skÉ;‚×ã„u¨óe"è–It¹¸e•2õD‘¦îÊm,j`xáŠäފǡŭõ$•ÎËHòô$j9•¥8nÑ^˜&±¸É•w•% óˆÜpû÷Ÿñ‘§Ö© µ™§&ã39.;UrÔ:%~Y#`Q“xwŒ!RcPû î é¥‚«Ü6i¸<ïáÞÝıBªú¨‘é鈃Î0t/Ýcý²‹Ê9ÇþÉÊኩïãx›sûãQºjDªàÈ$¨,jåE2®àOü:œ¸•¥»~8 HÔL|æ4B‘¥¸@ôö¢)oJ¬†!7åÒÂ/6tC2¸9¦,e‡^)³‚+iVÙ“âisk‘&zBÛä$H_ŒKÛ©ño&^}Ù†^ðI¬£×Ø”Ž5#œlUnçi½HeÆZÖ ¨d50WópWº¾ÛXSG—kž‹@€‘°„ á•Yï•\©»B%Œ›“åCx+“Œa‹0zŸ…6wñDnÒ¥ÖXb:>à±£í衉ÚÏi޾»G—¿éŒ¡9qʾÀ”©Äà¯öú,(SÐBÉܾ¯x_n:.A·º'Œ…•7|”-ÞHK9 •ºP[/‰~¢G^jHÁ  &a™Õv t¡ù¨¢+ƒ±ºþú§hÿ},KØ£ç‹ËØ4¹Þ¯Ø›&‰‚:{f:ë2âÎè ç|ýÉOóâU0ñ£B3àªS0“ÎÍfqðÞ'ÁvH½×©ùP6qìeê½iNûnHƒéÞ,í†ô´ „®]ÌÅ5»¹Ö:!LÆàú‹¢ÃdæyÎÓmÊ”yYÊüeÓ ße+­üªî±ÏæY`ºÛ𶆷^9ó‹_Qk7ï®U䉼M!”¶®‡a´Z¤ÞüÖ¨U£‘bGGr4¡fx*ƒäæH–»ï„ÔýM-×óEë\x_}f¬ê¢R¶-,K"‹„‹Ô²3`¥æ qlƇêŠà*‚1?¸®¸§'6;!…ˆ…Ë6íc).qÇQM-º­Z·™;¶ }}9}"ÿ–06fTDÛæªi>íS/›Ì§†¬•àGM|q5w·sf§Ÿˆy¶apÞo½˜“™æ¡ i=>¦xÛzÝ:@÷·äm‰)^ÒóÍb£~Îúíl-I¬.ǾKÞ¥< 0ÉÈ"½Sš6¥^5ÅôOì¼Hˆã#Ó€¯R¯HÍ)švøuêdµX÷yá2àŸÓ€»´›Úûˆ×Gôó«Òf,Õzr[ÖMnù…wSè´ïO½ÄX6úÇJñöò}ÌîjÃ:_ L醖ðƒfÕ«ZÈñ™²S´àÈœ Ö—o‹nåé±3¿À穱3?ܘ~… (¿GŲŠYR®t?#(—UõC2:½ûE¨ÄF(/æ­ò{ ¦ŠŒ7:qUzK²iýˆè2ßÈ®Žª$µ'8èi +µ?Ç*._ÜýØË5ŸQc‹ž˜ðO›Å/Kr­ùMúeIÅÓýŽDù#Xy>FctëÅ≠¨`å-e¼êJëu¾‚'ÇayÍêàøäKwt­Ò«ú§g,=b™e–ÙWòr΂츙²`{¹:1´÷R=¶š×izlÖ¿Ãb¹‘Ð`ï›Ô$±Ë4¶ !®Ì²ªù‹9¹J£`10É–±'d‹¢ÀÁg£½WÂ8{t´ðXŠÇöu ÍäÖÏZé^ö¢‚ÛÒàô•sUýRL½ºÈªÕ»ïNV6V3ùü5زÇ2í$î±õêÈ'R$Yi¥ìÔ˜GêNvs_Ú8Í53|ø–| ƒÔ§dè 5,¤®fŸfvJLéDR¨úö#+Oƒ /5 Ã>*èU&ËZŒ*•¯(Yž¬\$Ž{–lÎoÖ˜5›FNÑàxõ³o½ ¾ÀKˆ²ÜÇw«JºÂq•Ö§¦a´Ö!zåÁÁ!;’J‰à¸<­èN«ÛÄMü4 .ž?õ‹_,@a ˰†y²UT¤ ˆáÅ;ÔòamT‡Þ{úˆvÌÒµÏfé›@/ÛÕw2Ë%¼§Pã¢<OÊg¶X ``T B‚’DÌÆ÷Er,_ÊÚ‡­`þ!˜¯¿ÍÆ,‘†]ð .ÄÛÇá?øœ×O|¿b<ƒX–Ȭ:¾íOçß»åï»PWÒ{gOP9ꦟï§R——A[’Py•z‰ öÐHο¯œyæå?,SLj½¹„tNãf,³Œê~?×*ÄpÜÏ)¼”¢×"ÊšûÔda VÓHù™ÿ»f¬*ÿefô,¯²ã"wqɼ¡^¶êweŠ/EcOÇSëyé²_n"ÐÆ÷BM‡þ'±Kx–$ÁÏê1·žòÆ>˱º úçX ÓO¾dßͨËyûö"dVöBÕE– Ùå‰g<c1¦ÛŠ4¸ n8ô¶0×̤R¢RŸÒ×ý"„ÌÆGGJ„ßL£–²ê¨-4ü%='¸Œ;eŸœF÷`¸–³/0–]-Æc½e%Æ›Y›<5OQ¤æËÏà Þ möBºœ}oE×/x/’HbŒK¬ænIh“¤qw©—$ÏߤÞ}ê%)õ¥¬ïŸ>í¥•õÜ“L]eI…ýü^þ´'7ñqv)ì=ÉËïÔ,ËÄTò&DfÛO;6S&‹/Õø}±îˆ“+H`%‡>M[™‘sœ ÌðÙ½´!÷é78õÕ ÞŽOW7 ä'î ï1)ý›BI]µ5Sïƒhëz}Ú†P Ѫs¼wùä@f×Ñðl'Þ[IÕT›ï$ºûQOVD )cq¾Áù]ý*Cü&Ê‘ìrA™¨«‚Wc؇L„ù“$¹®ÌY&ÞŒìh²²Ä Ö¾\ê¤é#Ån¤xþ„]iô;Æz~|8SÖ!ÿyÃÂsjšë ò±ªKI÷7©ù ” ‰µf̵8õHñ±*Oè߀ÖÙÕ{­ "O½W_=¹µ{õ»2zÍNGÝßãTØø‚bzƒ˜f6–Ñ`»p ‹ÏùµðB¿, 0Þyª‹z‹a`UëŒý›‹}¹/õçê\%ÌŒ\ÈSsçá”®õ!ˆñÕ [2¦¤ âî!\³vùQz‡íºšøNÆÇvŠÐhþˆ2|Ñ4ñk¢$QƒN˜nÉhàgcóéêó­ñeè:>ú3ù¦¾¾8ûüû?dUè€endstream endobj 50 0 obj 5284 endobj 55 0 obj <> stream xœÝ\Ko$·|Ô%aäÐì´›o2N ؆‘§aØ+Äì´íîdg¤]iä]ùo$‡üÜT‘ìf‘MÎŽd+pÃpÅ.²Èz|õh¿Y =[ øOüïùîäï•Y¼¸9¿‡_œ¼9a~Æ"þç|·øôfÁO&{!5_œ>? ¯³…á 3¸~vqº;ù¶“Ë•s®wRtŸ,WC?ÁŒÖÝz K¿ºï— ƹ“ÝÙe=ÇÙL9§MwAž×ËWðk`Ýg”ày÷ƒôøâÖ?3k»kBålïðÁrÝm`Ê`µqƒÉÀü¿Ÿþ ¸tÀv`È$—½•ðû—“Ó_Û}³4¼·ƒQÝRÎ8©Ã2b`àp³B `N„aø5¤µXöÏgˆp¡Xw^”VÁ ÿhÏhÜ’Ù¸çA BIÖ­Èòç‰øU9=>àÏ0þxAþ@éÓuɆ÷›œjàUÀ.–LõpCïÈß÷ÙRÛ‹È–TÝw]Ø3gp ~ŠI#â1œÐ-_¤Ì7ægo·wi~¸G&²‹äª7Z€Äž®AH?„ÙœëAHOœsaœîöiô<=’¹oÓÜ»4z×娟›ˆUD̨ÞêA;»ªßB'ÆA˘­ðt›Ö¾©î(̵Üðn›F¯Òèy=KÛ4áÃ4:;Á’™û6M¸K£×it]Ž’Ä •dÂôr˜îö»% šíÊ%9N|s%ë¶‹½’Ò…WÖD›£° +Qª§ç¨äƒ„)» Õ?kæ4ØÖ½Z¢áCKú {ç86ýŸÁ6uÏÈÝn¨€¯ ¹Œ6ÕÏÜ-wª{6q0ý mTyoZ®È›[úã÷ `uF…X‹—3uózµ#ªW]ŸZ‡œ£Àµ4ÝŽèé%‹uLÒc¡"¿Yµ×a¶{M·Av·ßg'Ú:¸6îX÷ò7pB®·`Ëéú·q[ZÒÓÉ8ˆûftÂõ¥K€‘±Ê‚xQ%°Ÿä‡Ã£fÝëòg67Äžá¬P¦iÝÏÒ«ÛÍé!9^ :G» % »‡·$Ko1ÒñŠ8ž•WD%¢"ÆÕ¢_ çg½Û5^.ªhÕ¾x´|<ú_%Óñÿ(SÝ—iô‹4úyi¨üh_Ú,?:³Y~tf³üh2€›eÁ[&IAuR9ˆ’âÕ™‚u8 %DK¶äùœˆ[@OƲ‡i®ŠXjO-…qcŽeо'[x§(Ö/]¨]&M8}Ð"¦»'ëÓí^^µÈÕ‰îvßÀ—•À^P ê~êÕk#ya.ƒ”ph9 ÊônGæÌÜÁÜŒ2èõ²®}W“rIºˆ–gÔ(³¤ÐœLÎSØÞq]8Ï BWèÏû[x–þ®ÿ™N:0b6··™ˆ—.ÈkÁ¿utû¹—Â)5{`uogãÌ€›×P0ÖÕÑói´¢ÂRô\‰ ¸ÍÁ.œƒ&Ûwå}¡²\°®:Àõx®ž c†Í<4™­7‘9þn˜ÏèµêžRÎÈžÈEθ2±Œ$Ã=›ý|"b›¶¶P8/&` ψÌÜݺ>£ÀÓ8ìXSSwôRð %p¼K•»`òÚaŠ/3Çéf ¯YLÀZÞ°KÇ µé6—’Û£§Ñ/£†@¸ètÓ{L?ÎŽ‘-Þ{Ï7he•uóàw$Á3”aˆH÷öîz}}¾<ýÇl)©! VS ò4Rg‡ ¬qÝK2ìãeཱི4ãÝôXQÇÈ?'8CƒL‡µF”'GAð‡ (àzàÑiù‹¾KÃô:)’ÞoÞFËo‘MWs~Ê>d÷±]l°=Ká‘¶« EÂÉ{!å´5Ô|ÐSØïþ.0ÎÁÑ¢õGË‘Éf·ÙýE§n†€ñA޹<”pšÚ‘…]¾šJ#î%8ˆøJ0g lwa1¿Y ׇr#É)¨^ i{xýжœ¹G¶ÈD¤øg:KôŠ&x4*Õ{*V}0¯†<ü§Ñã[t¥pÏÞ}–‹’Ä<,‘Ì»Z£”¸Žv2^>gn¬µÅg HxØo*ˆmß4¦gÙ‚fn«”ƒÂ£z2Q‚óžN¿ÄP€ “÷õTEˆð%ë)Sm4Ï‘LŽvÀº€”ãÒɦ¢|xÁÀ™™s:€*JAÆag؆_;Bm¤ÆZ0óãéVf)ln2X€ÐÕêQ’.ËÙ…íS.Ëe´‘‚v=üÅMFc^M.%ƼR róâ¥äFø¢ý¯ÊOáAn–¦‹j$(s\1E³åÇ|M#"i=°Üñd‚.Nï œÄ5‰üÏâ¼YÝ ær’þªœLto{1×4h‰Z›9èš rÃúAðŠ Î…2OÔ㣱 [˜‚ê¥f½–€éÁfan}òíSzC1Æ”ã_{´ÝÉ…^RŸš'ÈÖ4ÈÝ\æE²uÀ~¹'[~IßÏóJ8ß8Ö}£\òÁP”T¦ jjP+FƸ&DlOéêìOdOtâÿͲf3„î sÞÙ$ s™ ©ëlÓ(©8”*Cq9–™(B4›\ãóDb“HòÔE½L£gitWÎíÝç§'_H8­ÅÛÎ$À:±€«=öF x(7lOž¶kàc (ôÂh¤€× á¤ò¶O#Ú&=^¦Ç‡ÐÄŠIåWZqÓ …á袙VšO†Ò_³ÎÀ”;‘ûÚ÷ÄTQ\ü«ÒH*ºYJ&LëQJØ1sìØX ‰è2Ô®jÂ0Ä”äºX}V»22îËòÌ€ß&ôHg¯È”Ç+ª5 ý©òyF1ì–ÌíV8NÞJžÍ‹mY(TT³˜ppAl¬• Oâ&[aónG€d‘ÔCök½YF%O[•=ëæ²7w»¹ìeŽk52ŸÃ[šDÊ9Vh KÁ÷c!P5ÎU²ÛþÍçKþ MѬøv_5Õö ÃÇ MÁó*¦[¡ià ³·4ž¯€ ¯Cô&1Ã)w¾…›|^’ Ú:k‡¡‚„‰ÉÜŠÔ ‚1ügÙ¦Ö"¿OSV¢’`ÙRòôÙÂ9·$šÏÜ H ¡LËÓÞ¯Š…{Â0ß5†y¿,>FßÈ Y²yVØ“l?¤$Ü\GœÊ\Fýàù¤jd0-SÞþßååÕ å^€fšðÞLuC”#  MAÄ­ä‡cSÛæw~²c»K€îÖf‹±|Pj-„_óŒV±™ýÑ©5FbµÇ€àŸÕ=dó൭1 8SÈÇ…k| מ6")míó|yÜÁgË)Þ*@U‰Õ* V·tÖuÒš3z TJ܆›€ËüëÒqÌxe/^'®6tüÙÿF,xSZv¯û)®©Åw\&ß—Þ£D#$ê#îåY­Æ‚Õä–·Äd¸~wp›E†v¶Mâäˆ%0!‹29fGôBXð?°D—b@g>< º"z¤Ze3ºk‹+åÑ%æ§­ìïgòDmÆ.7`“ê\‡Wdeúø<3A½SËõÍ6>®Býu“S…u•¿_bo÷ÀšÙÄM š5¸g²jUÞ-ètlV=ÁmÇÅû0C8ÝŒ¢c£¨Ã/âtSÔ·|oü›Þï_TMã-}ç,XÖÃM£eòõUàŸƒ…ò!¥°½NzY¶H5J¢áÊdÞKÂ#ÇJ‡¦#ÿÜ õÆõ„pö€¾laèµ{½²†¨‘ŸJÍ7u„$F„D€Íõ’až^gØÿŒ^i¾Ç"“— /üïÆè¼Ôu7¢CÙ}ºDÅpÒ”4ÖÔ—@¬z?øò¬Š2H9åGjApta“ÝzUC)tÀÓ˜^pPH:L+ät¹?`Øi(ô`KØÔ¡!8Éßï«G1K¾øMXï‹?úº<‰2¶;«Â²!–`J ›8|«ûd¾êw­üíŽV‡Ë ’¬ÆMLxµÛl±åÅh p}Éæ ¡p ˜q¨’ÞjµˆæPc²)#oCLšìæW„ö;Ò»XsË$éÈíÀ5ÝqÎPìCÐõdöu §Užþ›}ép°’[ùˆ`„èÈ@냙ÏmùäJÀV¤ æåeÆSorù‡‡¿‰¨$©Ÿ„>0ô­$Y•»¬{#ˆ€“‘#=gžñ#oÚ v8ó˜pB@d0*ĘõÆQ'³P€ZÑ9Ü4&¶ü2±a/<Ï]z$^qéžJñý~‹ˆŽŽvµÝ!qLùÍá:¬É˜}@2ÚïvlAÃgæÖQí7&r,r}PßÁ¹£yÈ>C󫃺lµˆ,Ø|ÐØc‘¸D¢Zóìãq-^Â1¯nIb!IlC•ˆ¨oh[džâ Üñ²SbÜH†ôîšÇo•®t÷Fm“#K!M,cÐèÌ®THÊ)˜°è§ª¨óÍ |Óè<<¬ðå{Æéñ(ÇD{ŸæíQ…cÊT +D0û@Ï*nDÛÌu•¾$ôž¾NÊF¤jÖÛ]‡©v’:ŸhÀÁ~(¦W¥N«ìk‰7u¥¯ñ*‘Ecøû>‚™yÒ,™fdßJ€ÊKì]xrÀú˪õuªÏOÉ™ƒH15+í‚s±å ª‰1®TZ\ly«$SトgÓì¾Ì{•ŠäÞÁ^¥²ø‘5+}VÊN«î¸ž)ý€ÊÝJ*‹eËÂ÷†Õ¤Pêxþ¼¾_LËŒ+Ö«Â jô¤æ‘û'Ã:È^E M[`*³ðtbx úèfÍósB66É+&”Ëòqga Æ™=ø$Iîv頻HH ü”ˆâÝŽô¬ÙÇÖÚÀîÔ¼õp~~ xA ûž}ã”ìu!¶dØíÜî"¹ˆG#~$ê/¯’+òob’ɃæÐ§ÒUo:ž5”F·¾­`åñ1Þ9·•®ÏĪyC n釴fKGaZÀ Š£"¥eLµkL‚Ù¥Ú f™v hœ<^H<¹ -8ÒóÞnÂz~N(¯ Pí0\™9ûVSÖOÕìOó–’Ý3Ho·_õ@~Îjò+¼Šç¨füLŠ”ztaË¢/Œ‹Yh–n¿ÄÐpªÿ§D;ï"M9³´ÿðÈö-/•C­}+²Ÿ»ÒÇFä˜;e€fŸu»1WY6ö‡>ØÇÏèbbëIýðÞ u¿¼7MÞ¤QÒƒóq= £Vãz?ùIVT…Ÿýè=îQαžH%YàëŸÕé^W÷Hv~[K¸ü¸Ä½ \ÈÉ^…¯Ô¦l®–>'þÕɦN4®endstream endobj 56 0 obj 4356 endobj 61 0 obj <> stream xœÍ[Ko¹|Ô%a°§žÀÓáû ìn‚ ¯Ã®…ä°›ƒ­ÑcìI–FëU~}ŠEv³ØMŽdYŒÅÂ=4Y,Öó«"ýqÁz¾`á¿ôçÉîè?¹8¿=b‹¿ÂÿçG8ÎX¤?Nv‹ïa–°0Ò{æùâøì(.ç çzi¸]Xæ{&Ýâxwôs÷»%ë™òÖ+óßã¿ÃZ.‹µáÓ:X¼†ÙßÀl!¤õ¦û~*Ïu·É£—yô6žæÑ›<ºÏ£ßæÑoÆÑÈOy–ÕÀÐJˆ^3ÙzŽC\äÑ«<º«â‰ìr÷|ìžVe¾Î£ßæÑLáey¼Î£oóèyU¤wyôú«ôçb]µ¡OUU=ÙäÕóí¶*ô·yô¤jp_im«ò?{Îàòœì’¨·©ÑEݱ Ÿ3,~µ~ù¾öœìÓäbÌÓ-”èVÓû«È‘šW9â½àÒ>…#ñ(ë+˜[9Ö+§})´?Ã.”`m(ɼu%…î ‡€OÕ{åP™é<Ýæl £Ê* ,®`_ï‹nΕsB7M‡½‡Ù—„ÈIžMfÜÆµÝ;2™ÌØÊl“a²ùe azÃD÷k`Ô1Î1d¦©ÈœdˆtÔ“æÊÊA¸!ácZ_ºÛÐãú[ enGIoãTk™.̤ ~¾cÚëî5ÐS²avû ª†Û¨)%x÷aéAMœQqИ‡±ûø×Öùn³® “ž`¿y6-g!—7‘¼àë~LM*Þs§K.(âIµàŽw¿%SÒ¢Û‘á‘Çb!•Ê>-tvbÑJë¹Ù1ãðG2|7UZœ²‚ÅNw5œqÅe¯•JÁ{]8 ÊTº¬:&u2rj:LÁìÍô$<ä„ðNÊÁ² Z$Î1óª 8"ÖȆîó×hâÀŽâÇDÊT­ô»_®”WR¶û.»]°;“$˜˜ØyØSu3›Nû}˜¹Ë`]㔫†¢¨q¬³ÇÏP31ÕýgixºÕÅÑ)íu’˜U] !¢D·ÙnãŒV…S1\¥)ÜÐ)'ù DÏÄ»®'fH¨à«è7 lJ™ÁoJ·ÅÍø“Ý6št²8%ˆ*½` .“Î|©ªâ Ä1¶QÙÊ©¶‹R?JUZ^ª MÉBÖàÉ”Pü£)YêŒd]ô¿$+ô?-})2Á%{âÛ쉻k2¾%æv#4çQ…µ\G¹ƒ)Ê÷.Aì´°œAbú:OŸ¤‘ш²þj¸†3Ýë Q&˜Âú >Ìfˆ Ô!H@@5î÷KG’ñ°ŒqÓ¶¡_Q‰ýe¯0ÀMïŒÙþ „è‘WMÁ¢6‡ÙG=p®ÐÎQËÜ5@Á%Éx”ü/ËHS DQͺÈÖ ŸŸÛñ–S§cÙý°'ï)ÁíŠ0p¼´2$n†ÃáàÚ%[‰Bþ.Ñ0­0Þý†¦ˆíi:¤x0³ÜÆ™SR^r‡=„åI¢C=>ÞMuPñ©2æGŠ\:(àÐÀ6…„IÀÞ¥)ÖûBóו*Ø#TR„«pù:q ñ 2VL s uG&7 S¡KûäEœ•õé=ø8@{ÒpT´"¯çô‡Z®¼)u?Ma4ªn‡|(ÁDäi£Ôy‰é&)ì< °é?x±¦÷ƒ²T÷=ŒJ8¹5¬ÜLp Ñç<""­Z4ƒOnÇÿ<:þýÏÝJð~®,”Äž¨”æ?.kWˆ#ÞÑŠÔܤˆ}—GIá2®—eÉyQBj0^7†äyi ÜAý/ÇG?)8ëâcåz¡ §gn±ƒÇÇŸÛ£7ÍntÉÇІå=®'б½©¥ÑéŒ]ä¢ËΦ£øyš?o–²TÿxZ Û3ð•(¨côS¡ DË ¢I¬@qÞy„z­IÀ‘ÒB¬Ô©7#X’ÚÊ”Þ]!t÷%†ÇU¡P#ûEb°‰×E@Œue4ûõl<ý8/Ãp<§¥qª…ég˜/†š -K‹O,\›!ô& ÙYƳ¶ê’´J}qMªC5)Xj°QgÅ` ÆB®®ñ$*LÁŽ©µ¶7#™s7ƒ¦Ÿ½ƒvÔ"½ B£üµÊží(|3o‡àNGÎU¾¢±ñ²>ç`vb‹);»FF–“¾A=}–9’|Lò$øœúä¦Ñ@O'#D|K´]¨ÕH±ÈŽí~R€Òøü#®ØFu 2?-å˜þÚÉ_ɿȴ¹F¸6ÌÓõ¤ð]pQ…9®÷Pÿ(=×vÒ'@l(&¼‘¸}Ñà9BˆOÎÏj¬H`öå@ÂIÎz¤ÿ½­ŽN³^™‘¥ï…Õ#2¸Ê$Þeï«x0º2ŒaN;›2Ÿ7Õ„|^ËÍiŽÞåÏËü nf”è·‰IÝ\áè‡gØíj°½¶ 7xñ0nNõÜè§à†°T«lÀaWZuÑ0³½OÓ…˜‡%'¡‚*3z£~¡ÉýAÕ“X6 ž‘j‡±²Ì 3tM(úøüþÂ=óš yy0ë¼á'm*θ¢Ç¡\Å£U÷4-•OÃÕxæÛˆ„ @“Üÿ$ò† mxQ ¶N«b-rÞ¤£XP–éZ*Ó÷³Ðþ_hÖšùuß%*ÒtÛ 0±«³^ö殈?…RXÈÞAIù¹²%ÎBÙÆ¤_ÁôühÉ¡ÞÏ<Éìo#7^Êèèé»-õÍ“,ß@%ëH/ô8Zf¼i`X"iÊǵ¡¯­hö/~,±-ʬ}\ï;26ï}‡q-|«ŸÕÐØyÁ-‘ÌÿòñF%ɹ „qÞŠ9[°‡poÇU¨¾Ð» r;6gè3œÍP >4‚16K<5^hp[R+Å:AÇÉ5êðÀLƒZo8éDLà„ó‰Ÿò„×E¦[)p?ËÍüÇÔ©Bª?ÍŸëüù:aÃ釛ŒHMOÐée Zq¤'Açn§çÃQ7>åÑ‘˜¡`P YŸ@“a™K¯À¦㼺ŠÀò’ã팬÷š‚”ûêÜËÉ2†ñ§ÈþI^~œfÞΦ|*óʆ†£Í²gôãèTâéÌ©èíà¡\ô p/ðÕÀ{¥0…Kaø&ê‚̾šR©_*LÍ‘ŽkÓ*¢Ï@p€%ñwÜþŽl¿Ý'}Q|ˆ{꙾8ب±öEQa`J‡' Ââ]xØôß03„_N ö{6œÌÏ­fä/YŠ{ôõbé Š…”÷rþ AÝóU à&JysàÜóé®RÌìAøÜÇ$2Àá{n[í*™+ý‡#Tñ.fN¼ÜSrþžghͪÇÐoÑš:*Ùtö–ªö¨IW‚ÄТÛ7€79×S%ÌŸs ÉÆŒ‹/ÆŠ°R”G9NTZòÌÈÖó:»¸8/Ðʃuùðàg šlR?âí%ŸT÷ô­ú÷à ~ø…A£Ë>¾1“«2ŒŽúQ—õÄ¿à¾áIM<³)›> stream xœÕ\ÍŽ·rÜK^a`Àð, i7ÿÉ>$A$@ØVƒÃjwµ;ÉŒV^,ï›äqSE²›E6Ùšé‘d†¡EVÙUõÕç‡Uß±UÿÅ?¯÷_~£ÝêîÍE¿ú üwñÃó3VñëýêÏa70Ò¹Þ±Õó—a9[YÛ ÍÌÊô®ë…]=ß_|·þíeßõÒ'õ¿Ÿÿ Ö2‘­ÅGcaýó˜ý³9Æéõ­”Ž©õ>nÓè«4z“FoÓèc}3Ž"~~ñõ…ìzµzwÁ°Í$2Í;ÉVû ¦yßY7Žì.¾mD±™x@¡c}q/«›ØÕ6ÊQÒ i…a« ’Ò…óú¬ÎI£×á ¹PÌÍð|x¼Üaç¬Í'íÞ\n¸‚õfý†—¼7ë{2c{ãÒZ.a|¼?rýMzémš°ßÒ·ÞÚ†ëõoðýãKocÍú_—6Õµ~"+)»7a²u.²¨Üîv‘¥²½&Ï3àRŠ¢ç°ÃõU> ¬¸öáu—_³~î©p©z™R¤b{ëŰòþ——®ÓLrCßþ–~‰CÜ”ëí›ð¬„Zÿ0þeG·A¨—ç^° 8³ù¡/à¶D-×ç¶|µá¼SÌQ;M‘‰åܦÑC&í^#×@Ä­´ U‘;Ñ5Ž,PEî:aPàJ^»ÄÜÍÔFÀëÎP†Гú†0"UÎÐubè¡jööiô*¾j1_%: ï ¶C‰c;„c`ÕúPhƒp`>•]ãá—ª^(ÉÖûýUú‡ÂdàR§\¦oÙ÷Ê)*öÃlP“ÃC|–ùbÈq†up~Ci3{Aw¨Ó«õ&f²ó´¢´)ƒ‡L齃dëeÊ;Ø/ïU``À:iìœ9 @d'71Á.\§ÇíUzÞÅã‚õD„³B™\Š¢Ø vPòÁ¥5‹a;à€,Îþ"ÉõçþÑrç¨I´ÖO¸­.KÄ*ê t§¹1Ëɾ£ÆýFrø(F¥RÂ5vQ¢|Ý!ÎÎçiô‹9@©®wiÂ3||1…*0áq÷úøš(ꎠÕuzÌuп¸¦ð|¸OãWÁ€óžø#zêWIõöÄU@ž€šÓñD¯êħ¤÷V  ¶Xï2I&N¦iŸŸ)õ3<×.ã7ßóšõ”õ»Kø˜\KE…ñ0z,ÐCÖ™-šy5¼4·É”f:£ð9ø”Ã×S>ÖZ’ŸÍ'€€E}‚8r†OÀE'TtÏëÊø®í$†Ÿ`9CƒO@ú¤>Á‹'zDV7ñ xÏ:,-ð p)gúHŸƒâK™50]‚#|g÷¹ºÞ^¢‘Gï†=ðå(ÈÚÎGÀ>{Ê©‰ö–sK¬ènؤ¡F|bf#%Bú@|#"5íÌtJÛŸß%H´•92’Ȫ‚Œ0Ü×1˜Ezê;bQÉÙÙ…ó°àí3f m£˜íA“«Ž‰ša´Ò‘ R¿"êC”ǃ&®í£ If(Æß•ÛF¸¸s#×%_?L‚ ê ™Øíž.µê8y¯ðºˆ|( ïWŽQÙ£6cPü*TûÓÈeŸ’§t²hÚ¯•°»Þ?xŸ½G¼…¿ÿÛtº3…ã"sw(eª”«‡|fg…%ç¯oÊE)sµã@N§þ ®eùA¾ ¸q>ñ%¿õÒô“I”&'RM)$‰ÒØ®± nÐ/fÆà¢/Ãjoª&œ’T“IŒ”z0]aíTIRc,KʼnhØbs Äùe¦[”îþ™\«ad¹kzuðdêÞÉSÓµ" E×ê †¢k•1ôët­$|ª¸V’Á[ø"× –jXz¤k…³™S“äÿ!ÁÄc˜Á”m;\evÄ“s¶‡Öî<ï*°`ªIg8&0ÄÍè©'‡È¦­³ÙÕ½°ún…Éž }>Gîj¹T8Ûë1ã‡5˜ ó¥HÜÑroŽÌ"ïUôº³ZÞ«6 Hu¨˜9ÍÓ%Gûµ^|·D”‡Y•¢êÑM“abÔ¹ÍùµFu†+Ùôk½˜«ö€1“S¿Ö~1>62>Öš¦_{DÆgªX ôÒ{zÆÓ"ˬ|ôŒO PAÖ €Ú»%€z¨~?$IP+À±@̵RàÁi!”¡¸#  L¨Îq:ec–àPåˆðùº”>?z•F«j¨&t§•.5ø|X3ÞŒLa Њ€6•µ”&…¸CXª+ücÿ&3†(Ú9CíLU&˜ùcƒL|“ôôÏéÐþ>§² €f *©F›8Ç»ô$„å³û ua²q§ ´† Þ­F^gýu jØî§,V Ðrä±åly"¯®)=»Ýrn™Ì Ym÷J]Ƀ~&,H†+Ênò(^S³—”o ª¶5‹ÿ‚ÊdhôFŠMÆ ƒø]dêÓð¬~wYÕÎ0Qž#¡×RÄØ§Ñ‡ôøª|$fÉ’e·Uº³PiPZØÈÙ&è2fVê>œˆ(BRR±~V= ñ xYgžÈ±»”¶‹`Š]öÚ³KwB}cPBá:Xl›7Wéù„¦›òÃû OÕe³ ¿ð­Gª€&<ÇýVoêô)Ì0¶L¦Ä…STÂÙ5!´“: õSVÁŽ›y÷‘‘~¢å²£ÜG°e™Nà&eÖ}3œJøåm¯{˜hv^ìï«bÿöì=Ic¦{:&² »rVµv…í_æxó¶=O™]×÷²²• øÔÝ!KÝÕv Àó™j\ï×ÈWiôª<"­~Âdã íµè¬[E6N£¯¦ë];sN²zDxÿÛð) å÷1KY¢-í½§Ý0yˆ«ú=Ê<9à2±41y'Ç‚›¡ôœ%8Èy$¾?š³™žŒŸñ4DyìŒÈ \¢ì„0BYyN²óm)e³(b“ \F»’Bö˜Ýc6¹GDl¨ÓœÑYÃ?yĆ¡´büC'"áXÀÉ™b£u`/õ¢ˆ –*-§ ÜwÚŠÓB6ð¹?/d³ØèÐ Ù€W8¾ób6ؘ`óU–³ùÉü„˜Íùr²Ùà‘‹™Í³¼Ê• B 冪fdÆ|¸4¢Xl™K#&a6Âf#§!R‹‘Ó¸—†¸‡`M2߫׬h öÔ:#‚?EËjGØ\­j{¬kåé䲄ë“vŽŨ£r"u3ê@FÝ8”žKéÏÏó&Óo0}EÇÕJöxÕ`0¹TzüëéÖ–wº·HÂA­e™1%L¾N$»JÀuB¡…¨èl >,HæóÿLÁ‹Ã ž×õQ­?cÍ }·þÇœ¶ “å† a„OMZ„ „Qr RàJð{J¤ÀaTµ«H[ÐdLnO[•£Ñ‚o¯#.Ž©Œ=bKLÑÁsíŸÈâ VÞÓwÊ{8&Ï8Ñi§Û7ìbÖ\½||þ}ôøl–Q ÌLQ) gXጱÎ9=ÎÝ“ ÖSüôbZË™¶îÞÕ7DÅ-~p)4ELRí së~xch¤ñÏœ­¡ ð¥íÄÅÇVÁЛ2šùÀ)A½U½x½†˜©@/?<´3õãa¸jGµèR${.v9Êx Ø‚‡Øå ØVãÀôrÐÐ LÁþ"Ñ Ž‹³àëEâìm‚¤t».†²Õ>!¤íi3‰Ë»L€@§¥™t™K=wi”´zL‰ ²Þ×°¹šy g —yæñ—czâÖ+„o=È í!Þ&±¶Ua¥‹ò£/Vô,+jïÞ^æf&ƒç{jM=ª#ëûÜHLn²ô¼Óy~¡rWÐÃÜ=Ζ ®Y6eG÷Ù‚ûØ“LÂ>¼ÕˆÐ”°Á6(‡)=Ÿ±18[üöõ¶Æ–)΄ÆÉä9G_^ÂËóîþ t,• Ä€å)Ò™€cðý`IµÍÞm¢Ö¢‘wèùÝòp«ŸñrUá>Z §'m@ÿ¡LÙ \ç…¯isÊØœ!Ð'Ñ3™:ì4¼DÄÅ–0ÍyèVܼœ| Ü´U¼G‰H«Áåó=u>ó!4ë8²$ù!ðîzF°Mj ˆsèy»K£ËðŶÀ‚C7–Aë¶ Àq¦çæ.G0("œÓÛ«Ç*¹® ƒþMÖœrå/)0bR@öÃüØBd¦¨ÈŒ²ª¤˜A,ç> ]’gvÊgL0Žy†YM…)ZJÿûÊâcêîâ%&6‡ÁIËÒú4§0®¨¦F\Bì¡ú~MŒÀ?“ļJîߨ˜ä½¾›ð±þ™MÇôRH8·¢zN©‡—æ3(¦µ<Т§J0Öc¤èòò Ñ òH ¾¾Ä~Qì‰!*X­ƒ ר7)¿ùjï¤üFBÝò"×Í8š~Å‚O› :ÅÁ¦JÐGø®ãÈé6(tZH¤ÐyA£JJÜos$ œß~ÙÓCM­Kí®”ò†x¥œŸBBší¥ ûþ²Ä´¹$Ë^?jQ•K‰”¤¨:Œ,/ª…NXÝøªe˜_O “==ÔöÿÞ¢êX(Ê#~ä͉%?A8¨õQ?¾Æ²Yo éÇO „ ¤ñ†É_Y1¹'1‹´Ì‚ÛcØ9Á |xÓEöÀ‚Åçv`‡Ó .z½RHl¹ùÆ&|8êˆQgÝ»<'ÎB ' ñadyF(€W]êoËù™Ž’¹lþ²„÷¨î9ü1Àxlï8þpe$ú1ß4tÂo#4òÝÃUøÂ^ y­ìèEìFÙüÉ~jŸá[ dø’V:ÿ.;í‹ò§Ä?hØ‚Lòp¡!ìÐáÙ‡36j¦…ÒO¶<†_šO±yXÄq²©PÞÏž(TæeJ äÀt’˜£…ØAcç«GļK&‘*C#9ë™›$gýãcš01z~ô>ú«4!™·¨’ıÓlB¦ 6 Žõe@Rþz^ÔdyãÅOTOö´ö¼ zPˆI¦#N™Étp…W²&Ý ÓtÆbùæÊ‚ ËðIðÌ|mÊ?Z=“lô3œTyzáù›ˆí’gaº€oŰÕÀDtpþ<\Ä‘. ÞEànü"}‰lCœä§k¶"œÖûø!µ˜^›Eiß»¼…’‘çQ²î¦V³h—ô/mWü&•3Ž¿ Y€k͓ŨÖj4\åýËð[e2¯7®RÓ\"ù½ÓÅ}ˆ ¶z4ù×I&¶ìå ÷*&w ÑLéz„¡W ‚uLFìaá# Òõ°( 0Q«ìöø±º27÷ŠÔ ßUòž¾¦ÎÒ¶7µ;XéöÜУª‘KÛß6¤“ßZ#åšS we6Øæ.0 …ìðá¹`d}ŸûþÀ¿¾ø?÷ɹendstream endobj 68 0 obj 4667 endobj 73 0 obj <> stream xœí\Kä¶|œKþBçÀ#óý8:ˆÄ@Ø;AÄ9ŒgöÑÞé™õN¯7ûïSERRQ$ÕêÖÎ"‡À0VÍ¡J%²êãWÅ¢~Û°Žoþ—þ½Ý_|û“Õ›×OlógøÿõÅo<ôؤn÷›?^C/a¡¥óÌóÍõ«‹x;ß8×IÃíÆ2ß1é6×û‹mÿpÉ:¦¼õÊüûú¸—Ëì^¼´ƒÞ¿@o!¤õfû!\*Ïõöilý4´¢´ï¯/~¼PÓ›\åñé¢S|³‡/;x¡¾åþâEó&Z¥7 t2£ûQ›—£Ž¿W[I_™iþíOž>ðJÂ,p)7W\vZ)‡ãÅ匞fR+¾½\y¯ävÿòòJhÖ‘Z †é äwZJÚŠCÚ‹x¼ä Ÿ)A]¸ 9vý&JµV„чiRs”Ë:Řöz»{ xÈ ýð†´¿4­N90¨¢ŸòÛ0.†I´N£u?¶¾/ÆË»±ïÍØú~¸ÌCe`H7ÆkÓyv!Œ…iN7 Ð=£„NyIÍ‚htû½ú¤¯úVÌB‰Ž1p62TÉÉpßÓïã å²y#·–3e-ÓѦ`6s(„u’ >ØG¸“Îý]u¾ãÂ{ç ~—d{”®u´Í$${#*½»Œ#“ƒÎ•¼ÓÎmà¢ÓÜÅz~´éaÆXÉ;5ÂLßr>Ì+:’ÖÀŒ:f´\3Üv†™)Îp×qcVàŒPTf9ÎpðU¦NÃHç¿ÎÀ,±1Ú›†qÆ Ò -çOÖ(¡SëpFÎâ ïŒææTœÓRŽ3C—„x|5¿ý[…–ÂÀè÷6ó)>Ä ‘á 1ÑÔxûq”°3îÜOÔ&ø4Xw[,œo÷»YÈ‹è½OQ¤K½»?$͸̻ìÂ0J虜8EW‚9°'}UËD â[*Áìvw¡ÔëJ{vÀ]ÃÀ>g-‘ä¡›)©G{“ðL yÁîñFPŸ“fA®¯bŒP¦$›Êz«üÎAí7—N×ꯧ^ñ>©”êÈç±…’xíDDIæW¢d=OCZo««ÿîW"€‰ ¸$­ë0záF0`Ï}Ã8eDX%@@gœ]—V;XQˆÖóNØJX\FM®ÄB°lP+é´ö“ÁRbÄ®K öbåB°” iÖ,XbBÑ7áã,°ÁÏ×a%Êè+°2 bV’;ïÉuŒ6CäwØÑÁ}ˆãeŽ4¯´Ò9{ʣМi${Œ„kéN‡H¡]™fJí<Â%¸ƒN00…B‰>Á (ÄeòsBa|’ñ.Œuï¤ñà4â3±Âz0JZ‰»Ö‚Q ÀáôF3Ì1â¥À í[ÎÀ%€@z”‚–ñ? (©Ú««ç«i\çr5Vò?Xå€üÿO¿sˆÂ6ýaÛ:HÃÐËTè¦Q¥¡Ù±‚s$‰-BàúØä·Ls”P _C…%­§°„#ÊåIéXÏ-ÈKÉ<>ÃÝ¢)ÕÉf¡Y?'t‘iˆ‘m–À$í "^©uØBYm$Š%¬­“œÍnl}·’áYî7 ø –@­4.9CË9Ü … ”Ä"¨dð§xˆ™LÍÜd‡ó»H+ókQÀRiýB@„ÎÞËY@ÄÌîç ‡A¢+á·2_ÜF1&OÝÔ_)Œ„LÑdYþœ8‡nfË!Îá“8¯¥èNÜt/zpçg8À¡[Í6ãÃ!&/°8îê•XŒý½˜ žÃ¦²,`†Ê1?[ðß2“â¢ì׃°M#9€jYýÛyÓ¬Ë}§bÇq÷ޏf" |ÃÄ©™€) ¾E †QÛë0=°@€ÝMwcñMØÒÔ×c4ó¡|eåeÖ…¾çcÒš›Ö.5ŽÃûFÀsOôªz –’[‘0(›‘¡’f&7W±Ùk3 "¨Eˆœý»Ü샚™¡åÁ¡HœL|4ã$;gÇÄäèl-ØÇœbÙõGúfüö]CeºÒP‰ÔŠˆ]õç.±p™sùO£À:…a`Šl2ÒAv’>fkjܺÂÍŽ{‚¾×ù¾åŒMq‰Ì%`uPÚM·ŒˆnoçÖ{ÀAJÕšKGf…~Â2­×Œ–d a† —dÖ®.4OæÃµÕ ôˆ”=ÆË7s#'q—E¥‘H¼þµ²…®11aÖçÛéN·| !&óŸ½Yb@1¡;/Ib o9?1:\æö¹ÆdÓŠû1iA§`>LW²ãÞ‹JœT\ÚÕ™G¢–†éVuZÚYV âfÖï³h)ˆd° çlÕåa•Ò)MÃã[¥* ‚šÅßA¶‘rŽWbá—„ùùšž“2‡XpÊmVý_Q™&ügôgÊQA%²µ÷6ñQ¸‰ ØÕä ÷U‘Òe½ÞM§¯$Êtéݵè UÈ–tªS@bÿ.¸╘¤/Ž›,àéíòMœ2ÁÜ®T.XÙáñrñaÙL IÓë/H]CÃå¥ÇÄÈ€ƒß€rVä–ûûRÙÎNyÉ‚¦Ñ²>”¢áÕsUI™¼dá?Ñ6ç;™x£à±î*Œ_†v WAQŠW xŸbº –A×r!ŽD¹ÙÔÒêÌx´Z¦4ƒË"„¨Hy`uŒ!Â|ŠÎõ”¿°ßAoYÐÞøžýNÉà΃”†sÜ¥k]2+ ÷cßà]s_9p 9…lÑi‘[ªP%z‡hww@H€×* Fn]%M1î«ÁÜ´6–±—Çýžc?&6_¨´ ¢á”‰Ea}¾£Ø<Ãô”i-¹¯.=0˜QºŠe“ÀÊ©aJ°Ä^*@ Ú6üä|íbR”‘™ÿ„zdapÕ}ý þ={Ü»Þ.ÌŒõyŸÒ)y±K¿x‡ÝV9]@{\}©žz˜o§¤˜äKŠ»+€^KÏcìÉ^º£%݃ S.ï©K£Ò›òÀùå=)÷|%¯G/#éñC­µ(¾•B»ÎR|Û·œ_| :ãÒ) rtˆäùG•G”7¥ ié+‚¨Ì++D0éaT讪æM­o-jѲ3C -—Ûb•òìgÜ\L¾ôæ"ÄÄÊÌÖ®á)‡•¼E¦Ûþ4Ê?L[—%Ef~9eŘx S¦x‰úéÊ»brj…ndȲ¥ƒ€ñ4¨eÊ~QPõæ9á"=ã9N €óY׌œ°¢ŒHö#t˜­ÛÎâXǯÅìÅŠÓœÈ5“‡p¬IÊí™'‹Ëî+z°±@„NxäÚfÒg7’Äû»x¯êO fÉÒÙP^€ò!Fó‚2Ã>2œsvDŒ!׌\ó$R¨œýs´áâÒj“uøk¸Os ßÙõŸÆ.ä2Ô°ƒ†X ~j2>‰³¡u–§4Æ0Z7-‡|ó˜iK±Ÿ®Øö«Ñt‹X$#:Ü[—ý‡#¡"„Çm(Hvyq#eA¸]oÖÒò¹€0;{‡¡ºSf&ï°ØàW&ÛΤVf<ìd¶ßǽ(û}­ÄÐ,Ÿ,²Axn‡Oùú/¶¢kê 0"]ú–3Ô¡L»FBW_œÒßÚÙ TAªœ1hSk”3x“çÊý}TãÅ,ƒ„›­)và€B"áÁå{…D)ž‹e2<’‰9 äiù9)$ŠÊߢqÜI\ÑšÀÿ3ƒ¬ÐÝØJÎÏæ{iiçʃõÁüÂB ²¿cú†3ö­¸èœ›SÀCMªÜ&IbÙw³4?§àª•g+il˜f¡ Úœ¥±åŠm æÄ«,L¦æ·o,<»ÛøTëõBìIò¢9¾SN“ïo²[‡öQ¦]¾¹Œ‡Ðš$LGì^Y]*%€I¦lì[Þ3pžŒ¬òé½ä­wa-(ߣwg9±>h€AZF­ øÓý¦K=í¸0hЪ³l²Û@6k''h±ÛÒÓžånîݪé6 NO9Έشì_êø> ÃŒ/©o½I›˜!«~yÓÛ‹šK âôÈÊ–axAÙŠõ3l=¿/¹6ªÞ*–-¿ý”¤ù›ld¥VÜC `ôd…,Ï€jÀäÊõ%Rob+uîb?Ùlåæƒ|X`Ö¨·ÎÃ\4k¡ó 2ŠÏ:ôÉG½GA\`dÅ{¾Àqdt$e;ÕLæ”ù ˜(5|æ$°ÙÆÆ3-Y£(¾ãeB-âô„0M®ÐRåðñ^‰Pà‡Ø{#*ʾ¬ð»Kçæê&ƒiæ«G¶8-ɳ'µjÆ›D6€€ÚôTGÉ”4bû)·¯pOç%Â3ËÆs…"¤ †„"ä# ¿Œ­Ëjc¸ÃSôÐLßr~m wèšVk-ú"©?Z“%—‘÷I·ºPD–Å›Bm<09Ÿ\Fyö3WjóN)·¶TôU „9~Œ1sÚ%½SåwŠíý·#L=Å ¯–'Cú©ºKäeö/ ÿ #(ÖøjSÚ'‡€÷äÊJí]þÝ¥‡¨€/ËS“)c*h<ÛN$@D¶ çËJ ÜŠ‰¨ô9; š-Z°ÞûT´€sqÓ9£`w Ë>²ÏB‘ù§Gk¡Iˆ.¬¥N1]¤ëÀïËILn;Ãk5wñ™še97Ú¨¢¦ZÝåÓ<þxÕ• îá±P…à…W2ó™h¸Wi±8ÍCŠCƒÌ'eîFÏ S‹§z\³¦}x#x¡à!øý¶Þ?^:@^«,ö>Í”‡™ˆƒ,d7•Ϙ¤É±œàdΕv;U¾Eí£O…÷Îך×lqìrBÒGêLøÐT( ½Î·ïcµ‹æ|è¯m8Ї…<¿éWNLjñvw©¯±t“†®„Å éd2ÀNOQ0.ãS=€X¨ÃbX®[žÙp¼ýþåq;ž”u1˜V=•‚„jíVZŠë'”Ç”—ÅOëP ñ,›„P €û–3’^Vu`=( ™~¢kéW¿FG7wsâ?rÌï؎*+ŽŸ~Y¡±ÂJ•k\|¡+lê_è"ï:Ì~¡KáWܯœ,þáT­pýìÔa„¬œÏ¹9{¥r6;‰Èz<—NŠÉÒ¹µô¦Sºâ”Å´> stream xœÕ[[o\·ú¨—þ…EЇÝ"{Ìû ´EZ H[ÄVч¤²uñÆ»’"­dëäw†ä9òH+­»Éáp8—o†Ü_f¬ã3†ÿ¥?ßm^½v|vv}Àf‡ÿÏ~9àaÄ,ýñn3ûË!Œ(gžÏOât>s®“†Û™e¾cÒÍ7?ο`SÞzeþ{øÌ岘‹ŸÖÁüÃcýF !­7ó‹ð©<×óM¦ž TäöíáÁªczöñ€ ¼<®.:Åg xÙY=PÖo&w4’*í8tÒÉrG×Yšm–q•©ï2õC¦Þ’¿zíé‚K §À¥œ-¹ì´R>ªãÏ‹¥„]Iåæo£…Ô<¨†i&µJ߉¾FípåœPó£üy¹(}»ªsŒsúïëÂã$-)ù|ûžÐÉømâçÄü¸˜‰#¼Wr¾%ßW‹%°c‚ÃÌÍê¼=á:²dÚÍ?"Uh)Ìüý÷ úUdâ˜*´‚dí;oùü|¬ÄôÝïÈê1ó¤5­sS2vwߊ1íu[W y?! e¿>Žs °ÿµP×Àf» ¢iÁöÖÏýµ?I8±‹T¶³Ü÷ÎÖÞª E~S2nNò˜~áç—üÒ;©í|µ]Ñ¢GÒ)—½˜Á´’QÚÿàŠÞsÐb}þ½ U•[[]ã?¨Î8SHuIÜh,T˜ ˜Î“­)ÔNÖݦÑÚ ¢‘‹ñ`mÍpÇEçåp_…˜`‚Ä9R\eêMþ<ÉŸ_ c¡Dz$GÔ¯Q8RóI¿éõ¦ú¨¨§Ä²GþŒ»Õàªô¸ƒ#ï3‰·µ >ª2ú†Qr~†%؇˜±9 ð‹A•ßdõTI$P7MUþé>U*Þ9ÉM¿Ä‡8±â %ã ràÕãÙƒñÝ é°SâUàHú¢î1 ¨«=Š«õ:-j|<°šû¶pV2(E‹x8„¾^ßåÁ …wp@v”‘N‰ØEêY_„Ô•Y—çà»2¹D—)šï¹!^H•’"+{)µÛÈΙæ!bÃÛ´$ J¦<Ž“P°âvµ! uÖÀ¸sóà ŠPš©ykCÌQ OQÊhU¸@RI¿eb o-5q”‹¸ 9DÂx½&ž‡Ó¬³@§Øá.­[yF÷Ž d¡ctÆä°"{JCBtnpÜÓ('Ĭ k)ŽëhÁQ]¥ni„?[@üF6]ÇtÔóµ#+9'æ_øcÌIcÈ»”è—ÞÍ–°Í]ÜÊã°îMSç1’<°z«ÏÁ+€að?Û 73 R²õˆ‚•G©ÊP0ž®àÀAwΚˆ‚?6å<ÏÔãL½ÈÔ 6Æïàa€²-ÙƒV¹ØGd@üâA‘‰œ$“‚Ÿ-´ܽf®B룕`6BnGy·Éà ¨œÝb];;‚u×icïëüM?/X÷P¯¸„èf`ŸG”'‡õ[ÞÆ]X©‹4wœC ,w¡Kd}%aUM0²™ÂšÅ„%‰~ãü˜BëD ªO =W½`å–¦f^ 'ý1FHÜ«}¤ ŒG©+™®±G° W–*ÅîWÁQ"OËG.“y×)"ئÞUÊædÐ퀓tÌôµ^ð˜ûuc½G d4–*äff:gTŸ›µ²ÎͲi‘•˜‚Ü8c^š(×'QN©Lá8⬱¶HåîÖÙ¹$CTb¤@¬¿a?ÍóJ­"8Ä33äÎ?ä€õ×Ñþ•©ßçÏçÏä±ÿÌÔ7÷…<¢–ê^F‘=DEvÅÈ÷O‹8†ëñÔaŠ% æNÀó–ìxÆbGI„j÷ø ‡’ J 8„y[ä~Ê: Ž … ã9QV¶ë“ö¢Û\[`kú¢S‰KÍ~EáVéz˜A\§šFúJrˆ?F— €É¸ ˜ Áœ.j·«Ò¼#Ãì§à}[Äã±?øàuuab@¨|¼‹ ÞDháÛ‰}ÚQÍÜfêQùþßÉ4BÓN@µ¡õ”§#4àÐY®*¸Cä¼j¢ÎU“zVH?AXWi.ê–¥°jÓ=;–è!ªê@PXqÜ,APàgŸ!G{õ+QpË«va]îéW†ý@°LQÌê{£XP¦zRû1Ì•f:8]fœ¶&ž{—¦ªGQ.ñh…õe°HòŽùÁIN›2x¨öª`†¢ñ MöН°NäÞÀ:ôXïON}w3m­W;u7%ä6?:Ʋ)°Ž ýŸV ƒâɲ9¾Ò ¡â¦ÒÒ´‰+º‰°Òs³›ÉâNœÄ8ñ¢8Ø=œ¬`¨[ì @áŠÓŒE¾s˜åþëÅHoÁ&7´›qœ–&?Æ’žEQPŒ’q h# …2œÎeU´©MŠ4„¶e§yk[Ô!;¸[Pz¬¸——y[Õl@VFMyÙ2cÁà1ÞÂ&%š|‘ÄrRw°Q¤š¡ëVÞª\¶ù‘¾åêw8¼Qëô7Œ4"?E¸ȈHé¦6Ê·‡l°¥)Óê ãm`iÇ®5…G‰²<‚8¡µˆðèm–ˆ\5¯[ïAô3\R}&ôf;ÆÖcôÃ! ©/þ@ºõüÅáÃb|/ø3á¦;:i(÷ìÎí˜xY‹±ÊöÎöŒˆ¥áÒÒul +)¬Ë£©µ¬;klÔJJ»Øíéœ8Ê6á%añ¢Ë—êoXÉâ½ËEŽXC4ÄË>bþŸÓÕ†V¬›©­¨uQÄSr!E¹¬©ÔÄ£§îN¾^´o†u§Ýp×H¢Á^äéI|NÒwkBè%ÍØz'„NÁ­È5P:Cggµ:/u œëaeŠoÇÔðIÆò"Ö¿zíŠõ°EÆÄ`íß ¾¸7¾Ùãa™²¥®È}yè:S[ºòÖ¢F²®ðdáèöÐpiæ9´%î×¶Þä#´Åå^Ú’øQÃ’Ûlfe9ÕÄ|’²5Ž<+BcõqÊŒ+ÞÆ8-m? V~X@€¶Xu)~¨íê‚­¡.ª‚p·cêX]j¤®é² ÀãáÏ(ˆZÔ:a|Ù†¾mSHF®\rËÌbØztÚy8€š …5Ó‚Ù¾%GÉ8—&€ ÃICd?}ïâ]6~;뙾ä±ç-ñ…Û%™FÙ]‘oÂ" UÎE´Ê¡Œ!«¤TŒëh: mCs‚au;;üþàð?ο%÷·±ïªUUšH•ÑR ¶ca ë8)'_2MܺP<8¾,µ ÕMÑ‚…¼øB³þIœf…ë“mzuÐ’ní¥Ô  +¬hßh|ƒkãÛ€‹$gã¥MXEÕW­ƒTT§ (œ(_„ï)"?©'AÁèõo]AFÁéÄ»Åþ#ü”ПÇVO†&€Em¤z§—)«·í©ÇY«óüý&µÒòb4½‡©­ŒÃˆâ"¨ãô/ôâkxã÷WâÂÆe^@vÃCÛ£°à6ÓÚ׊ý%†‘ùêAû€kw9_Íü¾hÜ& 0S‚\°¤çÌFž3áwý;#·—7ô]ƒÊû'zõÊCÏ/«×Ý&¾êuuÔò”NÉ—är„ôÛøz æö€ôbÀ&ÀGC{thø@yJ{@tW‘CÇlL­]RT}‰}Ûq`sC¾…e vV½tS4Òîò..($'Y4†^PYÃ^æ÷^S•VÿHn¸×¯^k\ØÍnBÉý%n¤ëœ!¢§<=@‡ÎÀŸÁ6M;=o G~ÿôeÃ…úmvõCVz©ÓþÍ‚„°®’‰DÙ#HÛñ܆ñÿ.vzÖ›ŒwšÙ2¼87qO´9%Êñáì~8øå›Tlendstream endobj 80 0 obj 3291 endobj 87 0 obj <> stream xœíZÍn7zÔ¥¯°·®Šˆåÿϵ@Q ( ¤ÐCÒƒc9Ê6’%Ûr ÷5Úîì’»®¸’,Å®ƒAàõ˜;r¾ùf8Ë«‚VÐú_øy¾}÷«uÅüfD‹áÿ|t5b͈"ü8_ßOa7 !Ž:VLßü묰–ÍLa¨#TØbº½)¿SB¥3Nê?¦?Á»L$ïÖÆÂûÓŒþ£9ÆérÕï/ìŒEmœ—a<^Œ¹!ïZ£Ê·¥pÎxÏðêÆ‚J:€¤k¤ã±Êm3H}½T†9Î`/âàó¨eQ¡_ÞŽc¤ìuÇì"BiVEéf= ˆŸ!÷U-Tƒ´ŒQ€Ô,Ð3ÚÌ!³vuB'èÅe•²nX}_>“ þa:z=’`kq7b\ƒ.W(Ý„a±‰ĨN²ý6˜Ö{V…´ˆ°¢Ö@ŒÕ>­ŸEk.£÷4ãù‰€MdB“†d¤ˆ«Ý†³6hͱ®k]{Rê2ð¹‚Áó*°™c@ å’SÈŽ8j1¹´k™©Õ|zÙ$ÖÏ[¶ì5PÚq¢ÖÄ|s–Å(èFñPaúB“ǤLÞEÖf6x'Ï=Vv»‰¸;¸»Îæ¼E”.¶#† Lj…Àà 4S‡Š„ Y'9"T$'R»ZC]“øP™åª×ý ©¢t }L(»ûhÔTÈn¥œ)†–É™õŒpô2A€›§Ë¼í&Föæh€±º æžšrÝ;6›Þq¼ã¸[,Zz8¬¦@(=`¦j Ñ\š¦6ᇡàXÕe…MYÑä0TªQÉÐyâÆ«Ò%Á¼ŽVRµx•à:J¨‚m¨§«:Ò2Û…÷ ?W¸ÊÇÌæ‹Ï`!ðˆx •Ï h¾gÄq™-¿Ì–2Ëlx™s¥©e/ìð8ì°5e˜ .cñeÆUÄâm6vPô}LòW` ®‰¨+m`ñ5KHµä–Š8®k DY»UX£â–X´UXk?Ý™³|a= .u¸eòO|…ãS¡pøásbEÞ½ûo'~,\f ø.ãlæQàˆ^ÂmsŠŽVj%Çœ¢8±‚ÕˆâÊ;õÔÍgÛ{ ÀÁóšõÏV†B¤ëDr ìEß$aÎÄ& K[’Ý)›>ä”}âIâ¸SöƒÑ ¬¬ã ¡¡•Ð…? ÞN X?¶S9àýSÌŠ¯¥fβf"ÞŠE®æIéÕǯ†?BTOºþc?ë# .»>®Ãâ6ù)“d¦†5€!½¥Í¿­}`ª0?3@s¯B'_n5Ê­6Åñ§hߦ0¡M{—õ²m® ¶»¿íÆÚÄ‚ õ«˜ûQÛþÙ³R§À¡$'„¢EŸeûÝ­Gbë.a?[ߎ{%eWÆ.“F\h»Û§cñ§‚T·$AŽœÆAyäxÛ5°2ÝÀƒÖ'˜n`íHM8¯7ǹùN¤A`®Ä ±¿ûŽèäFK¢ ÏVr||‚µܪ±E(×QŠúFgÙXî_F` Û¡ ¶¤èöâ—ÝqÙ üò?g„ô]ÀÖ SN(O>­\æÇ„üBõéU¶0ë·ò€ïáÆ2bkýµ‰‡>È-£tññå–†Øó:) 2CŒÖÝÐæs#šmwnv†îß"±x§ lßÎÜ…œRÝ®-Ï";݇NCï³]3BAµŸÂcžò€.ßo_¸‘ î‰Læo 4—llIc__Èp{¨Ž;ßÈ|Rª“TÖÇ5DuArÕI˜Ž²çEu~ÕVèº[†Vmµ%Nž²j«Á»"]õU êOPÅXSß1/ÇÓϼŠìõ) G6JÂøÔz\ê7à¶ûÔ„Þª^÷4)4ÎÛ§^thòbrÓñ÷1Tý–•Ü$ºÈèߌ`јƙÍe$fÒkGÅï¢C°/Q2˜ç„Êó@ŸáˆÙŒ[5Gï œc°¦—4?±Gà9ºõÙ‡P÷ÑC(¤½îÞŒ0I ü’¼?p-³Ò&-€jö¢öOŒƒ­J'óasÙ^1bÏÊ¡ñæbò9r?ä¿ÂòÌçÖÆœí vÏ­NìL¨`?u1‘šHe‚zA¤l*”×£ÿïÌendstream endobj 88 0 obj 1957 endobj 93 0 obj <> stream xœí[Ko#¹rÔ%¡oi«ßä ä²{Øäà‘e[YIöØòxçß§øj»Ù’%y2ìb1N-U,¿z’ý±!mˆû/þ½ÜÎþôƒ•ÍÝóŒ4ƒ?w³3êg4ñ¯å¶ùËÌb(%–6W·³ðsÚÓqEu£‰í7ÍÕvöSûû9éˆ°Ú õï«¿»ŠŸº¡6ðó«˜ü&3.i{ c*¬¼}ž/H'‘V¶ûUOwüþz5û~&:"›×eŒwB¹õY'h³ŠT£=e3ûçäžlmKÀ SAÞÒ ’rÄ4†‰vó€þÇKÂ¥ NÎSY³ ¼“Bذa¼3Äi»š/˜°¶“a6“øèBSOŽ ³ÖÕ®æLt–IÞ~ÂRbÉ^²di}ª)o¿ kR ¿º5™`D·ëý} [*@/€b:,Ê ƒim>’v»Þ¡¥°¦Ð¤§ÀQÝþαIS6iÛFšA?Ý ñÒµ&€Šb‡»(11µ³ |ü| ?çá¨ÂœÑÞ ?6ptŒu’špr#\S~ØÏ0Щ­òºe •í:S÷™ºÌÔûžÚcrK;#¥9E9 8rE{Ê!„L(`ÊÖY-Ê_³ë,Ü.So2õ¡¶½Š¹/ï¨µÉ $[A½e>°„ÂöCS{ôCD^eëÙðjÚ¾/˜xÎL£åsœö…E-¤ åay“Aö2àÜÛ‹û•¤ ¦¦cIœMk0o˜Em«pc…ÙÜ"ËÝG£·Bà —6Üo~ŠûK!Lï×[´îMÔ?ü`ä<$£°©#Î#Lz l˜¦Ý9¼q%ÀDE2»‘ ¡ô\-~vœFqúûyÕ‡p-;Áø%>äC6²U6½»#fŠ„ ÁÅ5]:ÇÁ%¸{ÓSÎp\B°QÀAA|`Áq&%>?|Œ‹\þ³‡ô/…ƒ‰[¬‘ Ë,õK¹x/T™2öñjWgˆ²Q¼ämôIJ²›&²¸ë¼$–%t½2¿9mÁ˜&¶‘ÊoÆ—$–wc%ʦÀlÇ w ÝSÁžªÂmOÈáV5K¯ºb8$Êy4s¸ÿ`¨mÓñ4Ò¸’@œú1tCÉ4΢ïú÷w¤iÈx!)ð † Q¥ÞYpT*ì‹úå„$Rµ$ŒÁið:ÈÀË-Wì mè9(ûT=2t8¯PÆ tQ) ŒöÞ eGñÔWÆEùªZBTÎÝè$˜¦jÝý#úÇK\|äÞÐjçf˜+•ûs{£já"ªÆoŠDm ˆy„Æâ8qGåkJˆ¡æ?Ñ OÓE‹9U 2c£€‘È‹2ßKl6+d‰r¾MÈFé;ÚDYßRdÍä…"CI/‡"£¤n“…Û‚âBóŽÃþ³Òÿ{+mûšOáÂé®ñ@ÔÏp¼êfɲì)”uw/ŠØNMF«"À}Ïõ(‚›>wœ˜ðÖ>Cÿ[2Ü.õ7é㤂4†b)ø8©Àq˜Q/pUîçwŽð´ƒz¬ýaî´n…>–éÅñæR¸fè”;»TöP-ÖÓ·¨É¾ß£µ<” â$×C¨|Ù «§qû®,vÜÞ <ä&„ëÆ˜Š›­ˆ¢ë5jtúU~sh°àÝAœ¢9Þ×”YîÑ/ å?6LÖzfAÚsœ2cQ¨±:à ˜í›~pÒTªdIÿjÑÉŽÅr]œr‹a ¸£…6H¬)ð¡éþYnú­!‚Wô—CieI…Õî+*ߢ§#ú98D 2!récSw6Sm²Òí^tѦû|¼Yý©ïÔâPò2ž ®õ”\€ZS%nÇøŽ<Ùs¦.óð)Ñ¥Íc¦î‡üÝ‹äl¢wß\i ub#f]ŸŒkÊ:Æ{ÊéîÛµr·ŽC'Lì“Ñ,+2™ †qzX ÀG§.‘Â×*¥¸¯êåe¨ä‰, Jjª©í|><ëaÃ~@”ùj!™ÀAè¢ìˆ” B2ãÐ1‡G9ëCèFñþbOÎĉ#.ŒÎ †2àâèL Ô5âÝ¢3ˆ¥=ÝKRIâ½V@ØÉ z& ņe˜x½8,øÇ¤˜—…eЄŠ2,‡u”tÁ8„hŽ ·¬ªTÚþÂ2q®Nœšƒäå%Áo¡ùך¹!Ä9ïšåüÐ kvF³SB3#„æ ¤ˆ¡¹â+†æóîbê}œÛLE—•#‰½­ÿcvõÇŸ¦®°±OLÁn6^i-ßôþd‹Ûä(>gú—zºôqˆé§Kšôï|‚&CSDzòvgz{J´?Î5JB{+Ô‹îv¾ÔžWCçà÷¼¯ÂëóØlÓS f ãá=µH”óŸZX.öeÐ=°Ny†zò¶o,C[O¾u;PB)ƒí(R.°#÷ÔUÅ·ŽèiÕu–YWîoâw2ȺЕʲzÞnRIÞf5À‚»G¡µ.a%8J@Ny‹-ð™ÖDŠÈËùTîéA,Ì7üL$kíY¯”4cÿê¬rîØ#ë‹” ¬Ï=µ lÅõ¡VFÕ¢ÐÕåñƒ©¥Š ?ñÜÍÀÖÃ*‚IñŒ°êå',A}­W„SèÿʱÇãM3@ˆ%îPkLZÖÿóðw)­¥)>E¡‚ão¨áîek_j¦5·-é‡ :’OÅ=÷v‡BY²à.%9W^bà ¨é>sr{â‚m{ƒD¬ìÝ辬݅÷CŒsÿ¦Î¹²î Y¦ï3Y"aƒÒVº\œ%2_&ÊKD"eKtoý=·ô–¡.àÑ׈Ž7tƒè+DG<+ÊvQØ]ÔЃ×,ÔzpDš¨d¨1uâæW¹Î䂞”u¯ÉʨŽÃpƒÈËþ¨â/ýpŸOÐa[‡¦o³/4Ã¥ÖÄ‚©(L+ {“—A³1ÏÛ]h«bõ°¢¤±&ìyx2…ôö1S‘rðډѠA¸ïë¸ \«¶®Ž0”†„§üqB”^k˜ñçùÂ>H·ëÛL¯bž{/œNôÚÏæVÑ„¯ŽO™ŒfìÐŒe&¯úaþäKRæ>vÉ&U¦u)áù& 2Q¥I¼ Ò= …öÃ5šÈw…üC pn&?Y' HÚåcAèù©>=äpÄœG0**Xûë’\^;«…pï‹„ën¡¹ݦü”Wü¤Ðù;<+ˆ?‡6ãî>¬Ò4ª§œ~&V|Ös踡“nÊ¿ ›‚¢[›Þ‘»‹q¿No\ŒH©¡TDk_2$kÏaµ»fɈû>/JïæB1)ÛÎÍ¤Æ ŸWøO˜ö8±S$!lIì/6*Ÿ«*}’ÃÝ«ê¿,,öTà9/ˆÆwy˜>Oäû™˜ôPV¸ÝT¿sÿÉ¢ÿ6†%•Ð)èï;gˆÊ”ÕzMÒøTy á&5)JRD÷ ý~ö_ñLtqendstream endobj 94 0 obj 2886 endobj 99 0 obj <> stream xœíZKoÜ6zÜKÿ‚nÕYF|“×A¢@‘f’l¯í(ÕÚŽ-'Í¿ïð!q¸K9ëuÜÚ‰–ÇäpÈù¾™áã}ÕZ5î_üy´ž=ÿƒ6´:½š5Õ/ðÿtö~F}“*þ8ZW?-}³ŠRb¥¤ÕòdúÓJ³J7–4ÜTËõìu-æ ›SMMMà³QÒHcA¼ MÓ.êŸX²F YŸ§Ö|2J¹¢QÊ4·õå|ß ~³õA:1ÈL#qÇãù‚IЮeýûÜ &hÖôk*3Æ5uŠÞ˜ú}÷©É•30•Ë¿–¿Â XXb뀹O]-›-|]¿£@GìÖ šÇÏ·ó‡î”j?¿FXÐKë“ FÔÎ5#Æÿ 5ð+À¬5FÕ+¿t —0¯æR«ƒ\nÈ4Ÿ¡Æ ¤ÄOK4°è™}xœc/6† üyÆašai‡¾×ÇIß2¥¿ ³” {–GëÆÍ3¬ gà¦Ôü8ˆPØ@<·î|b…Ž“òÕ \dÊјýÛíA±ë˜Þmz\ÏFZ™ûë­Zãpµ‡1Î5Q³–+ Æn|]°Dé0ºdÔÐltܳEmŽÓç3PÂd¦×O‹[Ã¥®[ìÌÓ¸€@ßâr“õÅsÈ0q†ÿ'ÉÝ*,†eXPN¤ä6¬Æ*´ÒV ~¶hólúY¹ ` KŒUn.>HŠ_ឺG Ñ}{>ÇÚ½Û(熩ŠÚ‰ÿ× Æ]¢±±lÞ4ˆ='ÈòzLã–ü£³IÎTôŠ`qç§ÂmÝ^… ri Eå¼îZ Ô>ün¡Ðweà7ź.Î[ò[±ý0™ÛÅH­xOLÔwˆ5hÔOƒÌCdf‡fªd]-—kàó}‚FèDyÖÉÇs3PϹˆ1®mÀƒùÓ˜k‚ôb”’ƒÃ­Çì°É“0u]ˆa½/œå¡ ¹ä2:Š›( hýø65= â÷x¹ã8Ælå¤e5l*èyÏó†Ñ1sx1òdÂlÉs ÿm¸Ž¦Ô>žë“Úä¹uÑŸ«Qê¿XÎ^ΘW}2E«G.VTkH Œ%ÝìÕt­”k%Ð@,S A£l(˜VEÃN’ô I¯“´KÒ>›Ä\Ag#–"Ð ñ œÊ/PLë?E`Qq–Ç8èp¨ŒÆw •«2ÊqîX híœr½+Ç®‹®¦Â*îêc°† †?P à•@U"1xÉþà n"¼GÉ¢ëdÑe’^&éq’ží^PýêL„S”·¯q:Š ö"²ž*VSjôX Ç±Š˜2á±9N®~S#«Ú“ ¬nÇ”¢³Ââ®)ñ,ÚÃÜ°Ñø7ó4ÂC§€­• ˜6QrÚé²u ÍeÑ¢uÑú³$]É„(F÷ʼLg,ÈËÞM8N§°º]а°q¿‘Z±äxlÔR’paæÙ0M•ï£VIÅf}4D¢|7ës(lò¡„‹‹%}0¢eÚ>Ì)ìL^yu©"¤IóCç_caÿ¢äük žÑ{æ»E2“ü‰ßÿØmø§åÿÈ?XCÌ¿A²?ÿ@‘öžùÇ÷(&Ÿø÷ð?šü'@J,¦_Ü}\môý²O ïLåÀZ?Ø*ÑyâHy½æm^]æŒt*ò_éaWÊ•X(m ’ýóh Tª­“jt&Ý—ìÜ=L¤mÆÿ‰a׷踡7Æ*&cv? CM§{|8ØÆ»‘ÆØ[ݰ°ìÐëpè*l6j»*©ùš.d®ŠHîŠRt Ü'i›¤ç¥8˜¸ ‰U.õî¹ X¹j”ìÁÅm´Ó)5rY„rÍIÉÎ@¥ášîx®Ýµ8RŽ5A¸ƒ,]ºž{òXÓb mÞè—ÇÓ”¿ŸÇSq_¶Ù âç)˜^GÈv²¦×›‰ 'žv  =–qp ²u±ïUÄ‹ýí‡ ÷µ7/ßó!n%)ªPF¸Ø›¥ÛiwþtóíôÄ‹ BæÍžP ‘Ú»_¨©Ü¼°¶B|›•øoÈX6¿*zé (EëÕMñb̘7;ì0›2ZºìÒ=<æP;<.øòæ ³þ¦wNHœ#7íið–ñ¾€R*ŸÊi°\â#å%~Ì}`ähϸÜ'¥$B’=r(J€HXF†Ü×'rø¹,#ÂRÇÅ®q=õÐ:Œ;‡lK“šŒ{ £`M¶ÓAAêïÍHW:0‚аCâü=cÊFêÒèØaº˜DlA/©º2+¶-ô-:«+ÿ+JP£á§F”$ûS4ÀžWlQ™üás” »SbÜ0míz¶ªœ©ñf„§°¹1»l ˜˜0í@5÷(hx ¨Ñ›‚L]Vyy„i³‘> stream xœÝÛn\·è£^ú AÏ6Þ#Þ/nZ4I“ ss”AÓI+ÉïzùØ®ý%ýÜo‡Ãsȵ¤¦y(‚ÀÔˆgHç>Cý² =]÷_ü÷|wtü„½¸zqDŸÁÿWG¿Q?eÿ9ß->:iL¤·ÄÒÅÉåQøž.Œé¹¢z¡‰í 7‹“ÝÑ?ºß/IO„ÕV¨ž|á–àÅ·n¨ |²†Ùç0›1®­êNýPX*»m†^dèó ]gèi†ÞŒP·ò''G߉žÈÅë#*ë5u;e½ ‹@¤ì…!ۣŸœ ž0ôR‰òôCÞÍ>ïq]=å›eñ*+©zfac+Ê{)„ ôžò2.)ÐfÅ$éמŽTÃD÷ÒÍ„KA"+XÃZcTsB ‘žªTX+¸§jB8Ba{Ê…ø4Ï~–„3w›ça¶SͶåà”ãm!$Û°¼Ö$\*‘ð¯,égÜ„%™Ýke’3åV¯~¸_2Ñk80LŽÛè~êÂÑ…}l.#>ãx` ܼcÉe÷ !tpÒ  š•Ýæ ýf‹¨øÓ2/n³™•¶X#JjÂmÞMVêRq™¡Ãœÿ)S€Ä.”æ´TÀøÌò^ËrÆg¶ç†Ö[Àä±ø&oîUº®äæ 8p 5å<Šƒä‡ÅáÕ’ŠÞ³ÝEæ@, ÃfÆš~¸ X·,$)!gݰ7ßcÖ¸DÌ—øMX¯Ò——,¸hœÈmx‡p®#2еGfì6X°×Òqþ6±?½³˜¥Éÿ+¾¿©2ÑU†>ÍС`¢ °µ^°ðí©t"À%\±!÷.{Ë`P½¥ì7Õ+©XÉßa~ @P, ëlž'/>õ.1·Åœ6ÛÀÚJb±Fb±I¬K¤Ž["…МçËÜ»‰„¤¦0XA˜h“ËϦDœc>u¬`ùÔ›¯HHÁ­Ø‚:xÈlØ/W\õ!Nù‰ïe8Œmz‹U0Û– )$ù‡% ¸äÀ‘;Ïúß÷yæÄJI: kp˜ã,PØ=3£È·—+´±?¹P`Ç/‘jNÉ0ûâ=ù“ƒaàÀO4%aÔºà´/i¯eè\ÈoKálKã*ùÙ…]ýx xk·B‡|ìÏÀ”.ý(ÐhÀæÖÂüEä€ä;¬µ1 7ÃhtU‹ób0à}ºr“hzpIÀüìöŧh)|Eø~«¡‡„¦j‘«†DÈžñÄTÿÎvä8Û‘>C_çá›»êgë‚"!r“Æ8ö€¸Ì»v‘›b°)3Bî¹5uIOÀÐ3-fY»‹ê>¯3eaNñ¡'<ãý9ä 3wÉ¿tdŸìé{Šö°ÏÐçÕ!Ê„î2mç=·åÃK¬§È¦¢1Pm0†7ÕÃ# 7 NaÊîƒüÙûY2ÞÏпäá‡yÂÉt(à'ì3ôeÞä è³GU("É&Ox ¡ÏD&áD_}P=Äì•æ|ü§É©sÏÌ{rÊâRšŸcïiŠvtÓqébœò0Ʀ ‡¡æã»ôÐÇË&áìÚv…BÜ/Rå¬cmÊ´X iX̦½™IÁn¬3¶ÑOó¦)ÅSÙl5ÞI/”Ù< 䶦-Îc e¨¹ú¬BÜ3œu(v»mÀì—Ç¡z#š*’}ðL$¾›˜·vi´}<5ÝÏ!„c´SÄ‚7E¸>níkðI-ϵ>é3 Áã^Ö*[Vk@ª'(º…G’ µ€ÊÉcœÞÂõ¡’”RµJ&˜å&Þâ­l1Z¥HVeÍNáÄËÃÑé/ .ŠeÏ—Ïðºé¾H‘IÀ׎2 E®Áe, Õÿ˜±hˆP!ó3& ›Zç“eM„weÕqL]4Öܧc©¿HlU¶CìŒe–«åLoô:œ€@ÝŽé ô>9RxmÕÇZàŠûè—Õš*üÖÇ®¾¦šJ8w*Ÿœ„ä”T¬LšŽ)Ó æ‰sD÷©ÏÒ£ Ý*beá‰V™>Ì ›¸Š“D.æ®TõKW\y]Ÿ<½9_½×“ äx®Û”&>ƒ]èÞjBµéƒÁAƒPª™©ÿ\H"USp+÷cz®øÅ÷.¥ “¨éÆWIܶb³» ¦&ľ1F2Ï0z"ˇûFÚΰ~–.–u8Ǹ/ í++Rsƒ‘ÁÞRšf’î2 Ò8l®ß&¹›–NÝ.Xs¥ÓÔË réô±[’SL.‹ž;¼TBî‡yìÔÓ¼\Š>D®–5£–ЧNþX©ˆ:MP4}­c-I²À)®[ýWGç*{¼pøÆ1U§ã’ÿ%ZjÕ®‹ÜwùŸrp•œ›Àˆûe¨sÝj){ϦD«è^¸7Eú¿hD®Ëâì€jO¾i 6Ccóa5#ŸÇÇS6‡mJ o›‡ç‚ý„ualK{»^÷¥¢µŠ\+¸ÖC1Ý[7îj´£Ï4V§Ù¼f|µ†°qt¥¿ÊÃïê8ž€d¼Q(ŶÉø6^ ï¾ Ê5-éTú`Ù“ þj8lÙ]öYÉM¡þ¦·îemZ¯“.ܳ1˜‰÷Ž*ÑiŸÁñR¡—0~à#6Ýsãb%Jiï*M·pO7S;»¡Üt ÆÊ®*ú^„5ÄœX?¶I‰—mÔŸÖiÓÂ]ÛJ“^£Q;as<íDlÉÊBÚ„OsÞT;Ín. pdÝá9(€Áê!¿oØÄº.d[ÉBxSfEƒ8ü»¤å< ´Â¦jÖ€UÙàv™ˆU*äBèIéÝQ^Í•5ŠÃ©tãÛ夊_t4ø½Sï—¸»J=ËaÞùµ‹Â”.¢ ¤‘|eP¹G"˜z{]ÂSGõÚè?Õ Ãv?½è8}Ì‘¨˜*ðo—ÊÁb…Ɍ׺šÎ‰œ‰v—BPŽ“$•&¸èª­A¨CµZÄ$àâä"æ–crñãås¡ßäáyøyžûU†~–‡oÅÁq|h”{9ù¹â’)¼Tzd:{dâf6ì‰=ËÎò³ö^/8©?ÜŽ>vàÖÈ?Ûy8bÚ†“7„)Öj5ï+Îí¼¹J€æ9^?7¢0=Ïf8„…¦}?—®UŒ6/ÒŠ¥Ãu ë4o’‹ë(WZÞäL[_ËŠ’ÑhÇY§É¥æö™nt®¹<œ¹Aeµ;丠¾)eð oÀÙ…«ˆ‘°âhøøEç’Ç.œŠðßÑI¼º0qf«¥;y…®K´Ý-›G½¹a²7r úñ±£ÍIÑk6I°ID&~ôÝ,³à|î¯=+Ñ;Ri& ­Ì_ºjØÇ`oqÓ0¸a æ"¿¬¯"ýV:éTÇtTÂÑ„Œ“£Þµ«þÒ9+4£¥ê”uiu}Ñ8Ìaºè¯Û¥µe˜cgrœ;Šk™·”L¥×z°™•ò'c×îh+¼CX•(]¤ÝKû™Z˜@²ï”«ióÁ`ˆ=›l3>ƪßÐà§Ø˜Ä2ƒö­†ï—¾ÇQõ¿F ïm½Á€ß} ¸D´oéH8šŽÖߌNnaêɇ «ðšpµùo«]D”hðÛt%§ ¾Šj¿oóp;ýÌCÎÿæ!B†J¥¹ WÚQŸÙËêyŒ\Ja‰kw'Þ…Š}õ‡²þâ=è@Âõ3£f®wœÝðîï?^uáa¶R=¸ãvšŸœ×èƒG S&068’æñ*/‰öÀÖVÛã£P^¼Ín\2ªgõ˜Ég5kÿÀMÝò–sî´<ôª)Ö~^¯Ø‰9ü~câY†Ê—hÖ¯†µ§¾ÃŒZŽÔGû{›% AKq;r/RÈòš—pv¡R½u)I­|õÖ—agÕ[ö®ê­†(ÍWoó÷}<–µÅƒ KU„}ªé 5>‰™w¥§XG-ê‰Ø9G5 ,¨fïšBIQk™ØªÀPEÅoiþÇfÏ(F.–¡žì†Ì”g;ÒåHu…~Z㬯øoç_C@wÓ– ÄéÂ7•dXx·{“Jñz^‰èCl®  ¥¬øq³öY¦¨ê®ËfhéD¬àBhàÛ…5ƒ€Ú•„Xì@‚À‰L?ê¶ épISü%Ú+%Õ‚:m£ã{z×±N9DÐ “ô÷¢Ž{$ ¤Ï½déƒ;&<(ñëa¸Î?<:>vŠ’»g,:4 Àoˆ4ÝÆ9ûDIî^{Š ç~ÈAøcÖ.¨„}ûö—8vd‡¦)áfRKE´îÂ: ´U(‚Äé¡ QˆåÖ•ý޽í¿(¢.OZ¯z#!š(«#1ü =¹p­©4<¡‹P¼ëõNtG—· ¯{®˜Ó¤ëòÚØm¯*ÂîrmÅPSå]Ë|ô³|ÞÓLà·y œèbÂM(þsÖ­^edè¶ZºÏŒ‰P\eÇÕep•Ž4Ô> stream xœ}VÛnÓ@}÷WøÑAòfg/ÞÞ@BH H(1w§ëŠ3N!`¨î'àTŒ¦Ý¸ Wᛪ?ä\ §ká³§4^«°ê*É.]vÔí9{6tÕy[«òÎI=¸`3GÞ2Ï¢ ¡Úô\FóäAÄ›ª­*– 8odžÎfwæv!}m핉‘ôWñÀTxîÈøš!Œ Åú.†dÊÖû#¡Meôm‘”av•ú “ä”uÉÌ2±QÞµ¬W@Ëíà¤F¤ ÒÞ¥©·Ðd±ëè±=ÚŠifÙ± i•G¼:z3:MÆ`‚…žïæŽímì& ŽtDÔP–‘ÎCí¥²¨–÷\– !õ&¯ÍrÞMœ!'E¾Úß±ú·¢ 1ôã {ÿ¸rD—2Ñã$±ÌÒ]EojU=i¨Ë#›;ãc’§l1Zz¬èVNQÌ¥¿ÓnþôŸ`s .ÐDåc æäµx¤Àýc5 „-éè×ÑØê(öþšhCeþÝ-Ó'y`I$ß8ìR6#Òõê?žÌþoÄ@¥Kãú³¾M "Bèx5+>Òã/3\Ôendstream endobj 112 0 obj 816 endobj 4 0 obj <> /Contents 5 0 R >> endobj 16 0 obj <> /Contents 17 0 R >> endobj 22 0 obj <> /Contents 23 0 R >> endobj 30 0 obj <> /Contents 31 0 R >> endobj 36 0 obj <> /Contents 37 0 R >> endobj 42 0 obj <> /Contents 43 0 R >> endobj 48 0 obj <> /Contents 49 0 R >> endobj 54 0 obj <> /Contents 55 0 R >> endobj 60 0 obj <> /Contents 61 0 R >> endobj 66 0 obj <> /Contents 67 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 78 0 obj <> /Contents 79 0 R >> endobj 86 0 obj <> /Contents 87 0 R >> endobj 92 0 obj <> /Contents 93 0 R >> endobj 98 0 obj <> /Contents 99 0 R >> endobj 104 0 obj <> /Contents 105 0 R >> endobj 110 0 obj <> /Contents 111 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 16 0 R 22 0 R 30 0 R 36 0 R 42 0 R 48 0 R 54 0 R 60 0 R 66 0 R 72 0 R 78 0 R 86 0 R 92 0 R 98 0 R 104 0 R 110 0 R ] /Count 17 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 14 0 obj <> endobj 15 0 obj <> endobj 19 0 obj <>endobj 20 0 obj <> endobj 21 0 obj <> endobj 25 0 obj <>endobj 28 0 obj <> endobj 29 0 obj <> endobj 33 0 obj <>endobj 34 0 obj <> endobj 35 0 obj <> endobj 39 0 obj <>endobj 40 0 obj <> endobj 41 0 obj <> endobj 45 0 obj <>endobj 46 0 obj <> endobj 47 0 obj <> endobj 51 0 obj <>endobj 52 0 obj <> endobj 53 0 obj <> endobj 57 0 obj <>endobj 58 0 obj <> endobj 59 0 obj <> endobj 63 0 obj <>endobj 64 0 obj <> endobj 65 0 obj <> endobj 69 0 obj <>endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <>endobj 76 0 obj <> endobj 77 0 obj <> endobj 81 0 obj <>endobj 84 0 obj <> endobj 85 0 obj <> endobj 89 0 obj <>endobj 90 0 obj <> endobj 91 0 obj <> endobj 95 0 obj <>endobj 96 0 obj <> endobj 97 0 obj <> endobj 101 0 obj <>endobj 102 0 obj <> endobj 103 0 obj <> endobj 107 0 obj <>endobj 108 0 obj <> endobj 109 0 obj <> endobj 113 0 obj <>endobj 114 0 obj <> endobj 115 0 obj <> endobj 116 0 obj <>stream xœcd`ab`dddwöõõ441U~H3þaú!ËÜüÓëÇÖnæn–•ß' }7ünÈÿ]O€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMØìœŸ[PZ’Z¤à›Ÿ’Z”ÇÀÀÀhÃÀ ËÀt[äFßP¾ÿÌœÇRüX;ŸñÞïÌ?Í´‰NŸ8iB÷4ŽiMS::»[êäþìû=³¡­¹­»^²»~rÛ´¶@‰-½Ý}ÝÓ¦L™6­eBýDù? ¿÷°ò•.üi¿ð÷²iÓf°ýNœÆ¾Šë2·‹ù|Î%yx+ŠjÍ endstream endobj 117 0 obj 290 endobj 118 0 obj <>stream xœ5Ï[HSqðÿqÓ×P FI¹±‚$-Á(YE¥vч¬Dzv¡Íé6oÔæÙñr6ngÚvt…nóZ—H½Øƒ„Рʧ BʇzB:g¡&³·ß÷áË÷óÃ4a&ÓTÕÜ*<¹{æ ‡1áHŠ#Ñ¿§SA!…t*~ýu?¯Éä˲Ã.VÞÑk,-]V£Þ`'ŽjŽ…¥¥%D¹™´µÍD•Ön ÍZ{"˜ˆK£‘´wå&Q½Û°Õ¤´¶“MÉmÅÜÒf'­D•¥‰´6ë­¤6‘ÈÖ6­ !”ªËÔ7+ªCvTÎ`(-G)(€^bX/ö;Cp‹¾ˆ ›ŒaŒ7}ð ªÖ :95661ù‘õ², á\tçÕj<*±B'à^«Åáhi©dðÞÞ—k‚ê%÷z;äãâmÜã+Ý’ù]ÏSÀGì× ºÌ¯{A/¸9ðÂ<ΗÁXöï+¦›8^>Ÿ`OˆV"üf[J„k¼OùçÔ÷\+.Ê%~œÞâ±õ-ÕÛŒ‘ÿì¯Jx s7Wîîr•d}é_¬è}xÀ€‹‰U3Ôz]£—ß¶>§D¹΃/É@m6kW—Ývé`èé 77–×¼*>ñô/x4= Í̼añááÁ`ò§_q6ñ¤h»fÏ'v*YŠ¥B€sç_ÿ¨Zü¹}ŽáÎÙMSpûꌿ’ôU$æÄø‚ˆ0ƾ ¼$^ÂVØ F`”f]þe>tÈ9œh¾[írö©…¨8¸3!zi†fÀ™MhŽõ§ž‰uÊÐ8„Ãp_½Kst@GÇ8„ÔmÑøÙhš˜å—ÅäëûTriIX‘{¨P ôB:JR endstream endobj 119 0 obj 696 endobj 13 0 obj <> endobj 120 0 obj <> endobj 9 0 obj <> endobj 121 0 obj <> endobj 83 0 obj <> endobj 27 0 obj <> endobj 122 0 obj <> endobj 12 0 obj <> endobj 11 0 obj <> endobj 10 0 obj <> endobj 123 0 obj <> endobj 8 0 obj <> endobj 124 0 obj <> endobj 82 0 obj <> endobj 26 0 obj <> endobj 2 0 obj <>endobj xref 0 125 0000000000 65535 f 0000065052 00000 n 0000070565 00000 n 0000064878 00000 n 0000062116 00000 n 0000000015 00000 n 0000002306 00000 n 0000065100 00000 n 0000069931 00000 n 0000068830 00000 n 0000069793 00000 n 0000069722 00000 n 0000069654 00000 n 0000068690 00000 n 0000065141 00000 n 0000065171 00000 n 0000062276 00000 n 0000002326 00000 n 0000002657 00000 n 0000065254 00000 n 0000065296 00000 n 0000065328 00000 n 0000062438 00000 n 0000002677 00000 n 0000007032 00000 n 0000065369 00000 n 0000070321 00000 n 0000069164 00000 n 0000065411 00000 n 0000065443 00000 n 0000062600 00000 n 0000007053 00000 n 0000012541 00000 n 0000065506 00000 n 0000065548 00000 n 0000065580 00000 n 0000062762 00000 n 0000012562 00000 n 0000017952 00000 n 0000065643 00000 n 0000065685 00000 n 0000065717 00000 n 0000062924 00000 n 0000017973 00000 n 0000023509 00000 n 0000065780 00000 n 0000065822 00000 n 0000065854 00000 n 0000063086 00000 n 0000023530 00000 n 0000028886 00000 n 0000065917 00000 n 0000065959 00000 n 0000065991 00000 n 0000063248 00000 n 0000028907 00000 n 0000033335 00000 n 0000066054 00000 n 0000066096 00000 n 0000066128 00000 n 0000063410 00000 n 0000033356 00000 n 0000036527 00000 n 0000066213 00000 n 0000066255 00000 n 0000066287 00000 n 0000063572 00000 n 0000036548 00000 n 0000041287 00000 n 0000066370 00000 n 0000066412 00000 n 0000066444 00000 n 0000063734 00000 n 0000041308 00000 n 0000046010 00000 n 0000066516 00000 n 0000066558 00000 n 0000066590 00000 n 0000063896 00000 n 0000046031 00000 n 0000049394 00000 n 0000066642 00000 n 0000070107 00000 n 0000069009 00000 n 0000066684 00000 n 0000066716 00000 n 0000064058 00000 n 0000049415 00000 n 0000051444 00000 n 0000066790 00000 n 0000066832 00000 n 0000066864 00000 n 0000064220 00000 n 0000051465 00000 n 0000054423 00000 n 0000066936 00000 n 0000066978 00000 n 0000067010 00000 n 0000064382 00000 n 0000054444 00000 n 0000056548 00000 n 0000067062 00000 n 0000067105 00000 n 0000067140 00000 n 0000064546 00000 n 0000056570 00000 n 0000061183 00000 n 0000067204 00000 n 0000067247 00000 n 0000067282 00000 n 0000064712 00000 n 0000061205 00000 n 0000062095 00000 n 0000067346 00000 n 0000067389 00000 n 0000067424 00000 n 0000067486 00000 n 0000067864 00000 n 0000067885 00000 n 0000068669 00000 n 0000068770 00000 n 0000068913 00000 n 0000069510 00000 n 0000069876 00000 n 0000070015 00000 n trailer << /Size 125 /Root 1 0 R /Info 2 0 R /ID [(Ê[Vq]ÐÍÛŽ!·ƒyî@©)(Ê[Vq]ÐÍÛŽ!·ƒyî@©)] >> startxref 70676 %%EOF wyrd-1.4.4/doc/wyrd.10000644000175000017500000003257610757447275013044 0ustar paulpaul'\" t .\" Manual page created with latex2man on Thu Feb 21 22:25:33 CST 2008 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "WYRD" "1" "21 February 2008" "a console calendar application " "a console calendar application " .SH NAME wyrd is a text\-based front\-end to \fIremind\fP(1), a sophisticated calendar and alarm program. .PP .SH SYNOPSIS wyrd [\fIOPTIONS\fP] [\fIFILE\fP] .SH DESCRIPTION Open the calendar and display reminders defined in FILE (and any included reminder files). The default reminder file is ~/.reminders. .SH OPTIONS .TP \fB\-\-version\fP Display version information and exit. .TP \fB\-\-help\fP Display usage information. .TP \fB\-\-add EVENT\fP Add given event to reminders file and exit. .TP \fB\-\-a EVENT\fP Add given event to reminders file and exit. .PP .SH QUICK START CAUTION: while this manpage should be suitable as a quick reference, it may be subject to miscellaneous shortcomings in typesetting. The definitive documentation is the user manual provided with Wyrd in PDF or HTML format. .PP This section describes how to use Wyrd in its default configuration. After familiarizing yourself with the basic operations as outlined in this section, you may wish to consult the \fIwyrdrc\fP(5) manpage to see how Wyrd can be configured to better fit your needs. .PP .SS OVERVIEW Before attemping to use Wyrd, learn how to use Remind. Wyrd makes no attempt to hide the details of Remind programming from the user. .PP At the top of the window is a short (incomplete) list of keybindings. .PP The left window displays a scrollable timetable view, with reminders highlighted in various colors. If the DURATION specifier is used for a reminder, the highlighted area is rendered with an appropriate size. Overlapping reminders are rendered using one of four different indentation levels so that all reminders are at least partially visible. If the current time is visible in this window, it is highlighted in red. .PP The upper right window displays a month calendar, with the color of each day representing the number of reminders it contains. The colors range across shades of white to blue to magenta as the number of reminders increases. The selected date is highlighted in cyan; if the current date is visible, it is highlighted in red. .PP The lower right window displays a list of the untimed reminders falling on the selected date. .PP The bottom window displays the full text of the MSG for the reminder or reminders that are currently selected. .PP .SS NAVIGATION .PP .TS H l l . _ Action Keypress _ scroll up and down the schedule , or k, j jump back or forward by a day , or 4, 6 or <, > or H, L jump back or forward by a week 8, 2 or [, ] or K, J jump back or forward by a month {, } jump to current date and time jump to the next reminder switch between schedule and untimed reminders window , or h, l zoom in on the schedule z scroll the description window up and down d, D _ .TE .PP Notice that if you have a numeric keypad, the {4, 6, 8, 2} keys will let you move directionally in the month calendar view at the upper\-right of the screen. Similarly, {H, J, K, L} will cause directional calendar movement using the standard mapping from \fIvi\fP(1)\&. .PP In addition to the hotkeys provided above, Wyrd lets you jump immediately to a desired date by pressing \&'g\&', entering in a date specifier, and then pressing . Any of the following date specifiers may be used: .TP .B * 8 digits representing year, month, and day: YYYYMMDD .TP .B * 4 digits representing month and day (of current year): MMDD .TP .B * 2 digits representing day (of current month and year): DD .PP (The date specifier format may be changed to DDMMYYYY; consult the section on CONFIGURATION VARIABLES. ) .PP .SS EDITING REMINDERS Note: By default, Wyrd is configured to modify your reminder files using the text editor specified by the $EDITOR environment variable. (This configuration has been tested successfully with a number of common settings for $EDITOR, including \&'vim\&', \&'emacs\&', and \&'nano\&'\&.) If you wish to use a different editor, see the \fIwyrdrc\fP(5) manpage. .PP If you select a timeslot in the schedule view, then hit \&'t\&', you will begin creating a new timed reminder. Wyrd will open up your reminder file in your favorite editor and move the cursor to the end of the file, where a new reminder template has been created. The template has the selected date and time filled in, so in many cases you will only need to fill in a MSG value. .PP Similarly, hitting \&'u\&' will begin creating an untimed reminder. \&'w\&' will create a weekly timed reminder, and \&'W\&' will create a weekly untimed reminder; \&'m\&' will create a monthly timed reminder, and \&'M\&' will create a monthly untimed reminder. .PP \&'T\&' and \&'U\&' also create timed and untimed reminders (respectively), but first will provide a selection dialog for you to choose which reminder file you want to add this reminder to. The set of reminder files is determined by scanning the INCLUDE lines in your default reminder file. .PP If you select a reminder (either timed or untimed) and hit , you will begin editing that reminder. Wyrd will open up the appropriate reminders file in your editor and move the cursor to the corresponding REM line. .PP If you select a timeslot that contains multiple overlapping reminders, Wyrd will provide a dialog that allows you to select the desired reminder. .PP If you hit on a blank timeslot, Wyrd will begin creating a new timed or untimed reminder (depending on whether the timed or the untimed window is selected). .PP Finally, pressing \&'e\&' will open the reminder file in your editor without attempting to select any particular reminder. .PP .SS QUICK REMINDERS Wyrd offers an additional mode for entering simple reminders quickly. Press \&'q\&', and you will be prompted for an event description. Simply enter a description for the event using natural language, then press . Examples: .TP .B * meeting with Bob tomorrow at 11 .TP .B * drop off package at 3pm .TP .B * wednesday 10am\-11:30 go grocery shopping .TP .B * Board game night 20:15 next Fri .TP .B * 7/4 independence day .TP .B * 7/4/2007 independence day (next year) .TP .B * independence day (next year) on 2007\-07\-04 .PP If your event description can be understood, Wyrd will immediately create the reminder and scroll the display to its location. .PP Currently the quick reminder mode tends to favor USA English conventions, as generalizing the natural language parser would require some work. .PP Wyrd also allows you to use the "quick reminder" syntax to create new reminders from the command line, using the \-a or \-\-add options. For example, .Vb wyrd \-\-add "dinner with neighbors tomorrow at 7pm" .Ve would create a new reminder for tomorrow evening. When used in this mode, Wyrd exits silently with error code 0 if the reminder was successfully created. If the reminder could not be created (e.g. if the reminder syntax could not be parsed), Wyrd prints an error message and exits with a nonzero error code. .PP .SS CUTTING AND PASTING REMINDERS Reminders can be easily duplicated or rescheduled through the use of Wyrd\&'s cutting and pasting features. .PP Selecting a reminder and pressing \&'X\&' will cut that reminder: the corrdsponding REM line is deleted from your reminders file, and the reminder is copied to Wyrd\&'s clipboard. To copy a reminder without deleting it, use \&'y\&' instead. .PP To paste a reminder from the clipboard back into your schedule, just move the cursor to the desired date/time and press \&'p\&'\&. Wyrd will append a new REM line to the end of your reminders file, and open the file with your editor. The REM line will be configured to trigger on the selected date. If the copied reminder was timed, then the pasted reminder will be set to trigger at the selected time using the original DURATION setting. (Additional Remind settings such as delta and tdelta are not preserved by copy\-and\-paste.) .PP If you wish to paste a reminder into a non\-default reminders file, use \&'P\&'\&. This will spawn a selection dialog where you can choose the file that will hold the new reminder. .PP WARNING: Cutting a reminder will delete only the single REM command responsible for triggering it. If you are using more complicated Remind scripting techniques to generate a particular reminder, then the cut operation may not do what you want. .PP .SS VIEWING REMINDERS .PP Aside from viewing reminders as they fall in the schedule, you can press \&'r\&' to view all reminders triggered on the selected date in a \fIless\fP(1) window. Similarly, \&'R\&' will view all reminders triggered on or after the selected date (all non\-expired reminders are triggered). .PP If you want to get a more global view of your schedule, Wyrd will also let you view Remind\&'s formatted calendar output in a \fIless\fP(1) window. Pressing \&'c\&' will view a one\-week calendar that contains the selected date, while pressing \&'C\&' will view a one\-month calendar containing the selected date. .PP .SS SEARCHING FOR REMINDERS .PP Wyrd allows you to search for reminders with MSG values that match a search string. Press \&'/\&' to start entering a (case insensitive) regular expression. After the expression has been entered, press and Wyrd will locate the next reminder that matches the regexp. Press \&'n\&' to repeat the same search. Entry of a search string may be cancelled with . .PP The regular expression syntax is Emacs\-compatible. .PP Note: Sorry, there is no "search backward" function. The search function requires the use of "remind \-n", which operates only forward in time. For the same reason, there is a command to jump forward to the next reminder, but no command to jump backward to the previous reminder. .PP .SS OTHER COMMANDS .PP A list of all keybindings may be viewed by pressing \&'?\&'\&. You can exit Wyrd by pressing \&'Q\&'\&. If the screen is corrupted for some reason, hit \&'Ctrl\-L\&' to refresh the display. .PP .SS ALARM STRATEGIES You may wish to generate some sort of alarm when a reminder is triggered. Wyrd does not offer any special alarm functionality, because Remind can handle the job already. Check the Remind manpage and consider how the \-k option could be used to generate alarms with the aid of external programs. For example, the following command will generate a popup window using gxmessage(1) whenever a timed reminder is triggered: .Vb remind \-z \-k'gxmessage \-title "reminder" &' ~/.reminders & .Ve (A sensible way to start this alarm command is to place it in {.xinitrc} so that it launches when the X server is started.) If you want some advance warning (say, 15 minutes), you can cause Remind to trigger early by setting a tdelta in the AT clause: .Vb REM Nov 27 2005 AT 14:30 +15 MSG Do something .Ve .PP Alternatively, if you want to generate alarms only for specific reminders, consider using Remind\&'s RUN command. This process could be easily automated by using the template\fIN\fP configuration variables described in the \fIwyrdrc\fP(5) manpage. .PP .SS MISCELLANEOUS .PP Remind\&'s TAG specifier may be used to cause Wyrd to give special treatment to certain reminders. If a reminder line includes the clause "TAG noweight", then Wyrd will not give that reminder any weight when determining the ``busy level\&'' colorations applied to the month calendar. If a reminder line includes the clause "TAG nodisplay", then Wyrd will neither display that reminder nor give it any weight when determining the month calendar colorations. The tag parameters are case insensitive. .PP WARNING: These tag parameters are not guaranteed to interact well with other Remind front\-ends such as tkremind. .PP .SH USAGE TIPS .TP .B * Wyrd fills in sensible defaults for the fields of a REM statement, but you will inevitably need to make some small edits to achieve the behavior you want. If you use Vim, you can make your life easier by installing the Vim\-Latex Suite and then modifying your ~/.wyrdrc to use REM templates like this: .PP set timed_template="REM %monname% %mday% %year% <++>AT %hour%:%min%<++> DURATION 1:00<++> MSG %\\"<++>%\\" %b" .br set untimed_template="REM %monname% %mday% %year% <++>MSG %\\"<++>%\\" %b" .PP With this change, hitting Ctrl\-J inside Vim (in insert mode) will cause your cursor to jump directly to the <++> markers, enabling you to quickly add any desired Remind delta and message parameters. .PP .SH LICENSING Wyrd is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL), Version 2, as published by the Free Software Foundation. You should have received a copy of the GPL along with this program, in the file \&'COPYING\&'\&. .PP .SH ACKNOWLEDGMENTS Thanks, of course, to David Skoll for writing such a powerful reminder system. Thanks also to Nicolas George, who wrote the OCaml curses bindings used within Wyrd. .PP .SH CONTACT INFO Wyrd author: Paul Pelzl .br Wyrd website: \fBhttp://www.eecs.umich.edu/~pelzlpj/wyrd\fP .br .PP .SH MISCELLANEOUS ``Wyrd is a concept in ancient Anglo\-saxon and Nordic cultures roughly corresponding to fate.\&'' \fI\-\- Wikipedia\fP .PP .SH SEE ALSO \fIwyrdrc\fP(5), \fIremind\fP(1) .PP .\" NOTE: This file is generated, DO NOT EDIT. wyrd-1.4.4/depend0000644000175000017500000000256010757447265012377 0ustar paulpaulcal.cmo: utility.cmo cal.cmx: utility.cmx interface.cmo: version.cmo rcfile.cmo ./curses/curses.cmi interface.cmx: version.cmx rcfile.cmx ./curses/curses.cmx interface_draw.cmo: version.cmo utility.cmo remind.cmo rcfile.cmo \ interface.cmo ./curses/curses.cmi cal.cmo interface_draw.cmx: version.cmx utility.cmx remind.cmx rcfile.cmx \ interface.cmx ./curses/curses.cmx cal.cmx interface_main.cmo: utility.cmo time_lang.cmo remind.cmo rcfile.cmo \ interface_draw.cmo interface.cmo ./curses/curses.cmi interface_main.cmx: utility.cmx time_lang.cmx remind.cmx rcfile.cmx \ interface_draw.cmx interface.cmx ./curses/curses.cmx locale.cmo: locale.cmi locale.cmx: locale.cmi main.cmo: version.cmo time_lang.cmo rcfile.cmo locale.cmi interface_main.cmo \ interface.cmo ./curses/curses.cmi main.cmx: version.cmx time_lang.cmx rcfile.cmx locale.cmx interface_main.cmx \ interface.cmx ./curses/curses.cmx rcfile.cmo: utility.cmo install.cmo ./curses/curses.cmi rcfile.cmx: utility.cmx install.cmx ./curses/curses.cmx remind.cmo: utility.cmo rcfile.cmo cal.cmo remind.cmx: utility.cmx rcfile.cmx cal.cmx time_lang.cmo: rcfile.cmo time_lang.cmx: rcfile.cmx utility.cmo: install.cmo utility.cmx: install.cmx curses/curses.cmo: curses/curses.cmi curses/curses.cmx: curses/curses.cmi curses/test.cmo: ./curses/curses.cmi curses/test.cmx: ./curses/curses.cmx wyrd-1.4.4/rcfile.ml0000644000175000017500000007450310757447265013021 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* rcfile.ml * This file includes everything associated with processing the wyrdrc file. * In particular, this includes a number of hashtables used to store the * bindings of curses keypresses to calendar operations. * Adapted from rcfile code in Orpie, a curses RPN calculator. *) open Genlex open Curses module PairSet = Set.Make ( struct type t = int * int let compare = Pervasives.compare end ) exception Config_failure of string let config_failwith s = raise (Config_failure s) type command_t = | ScrollUp | ScrollDown | NextDay | PrevDay | NextWeek | PrevWeek | NextMonth | PrevMonth | Home | Zoom | Edit | EditAny | NewTimed | NewUntimed | NewTimedDialog | NewUntimedDialog | SwitchWindow | SearchNext | BeginSearch | Quit | ViewReminders | ScrollDescUp | ScrollDescDown | Refresh | ViewAllReminders | ViewWeek | ViewMonth | NextReminder | ViewKeybindings | CopyReminder | PasteReminder | PasteReminderDialog | CutReminder | Goto | QuickEvent | NewGenReminder of int | NewGenReminderDialog of int type entry_operation_t = | EntryComplete | EntryBackspace | EntryExit type operation_t = CommandOp of command_t | EntryOp of entry_operation_t type colorable_object_t = | Help | Timed_default | Timed_current | Untimed_reminder | Timed_date | Selection_info | Description | Status | Calendar_labels | Calendar_level1 | Calendar_level2 | Calendar_level3 | Calendar_today | Left_divider | Right_divider | Timed_reminder1 | Timed_reminder2 | Timed_reminder3 | Timed_reminder4 (* These hashtables store conversions between curses keys and the operations * they are associated with. *) let table_key_command = Hashtbl.create 20 let table_command_key = Hashtbl.create 20 let table_key_entry = Hashtbl.create 20 let table_entry_key = Hashtbl.create 20 let table_commandstr_command = Hashtbl.create 30 let table_command_commandstr = Hashtbl.create 30 (* Default Remind command *) let remind_command = ref "remind" (* Default reminders file *) let reminders_file = ref "$HOME/.reminders" (* Default editing command strings *) let edit_old_command = ref "vim +%n %f" let edit_new_command = ref "vim -c '$' %f" let edit_any_command = ref "vim %f" (* Default new reminder templates *) let timed_template = ref "REM %M %d %y AT %h:%m DURATION 1:00 MSG " let untimed_template = ref "REM %M %d %y MSG " let template0 = ref None let template1 = ref None let template2 = ref None let template3 = ref None let template4 = ref None let template5 = ref None let template6 = ref None let template7 = ref None let template8 = ref None let template9 = ref None (* algorithm to use for counting busy-ness *) let busy_algorithm = ref 1 (* number of minutes to assume an untimed reminder requires *) let untimed_duration = ref 60. (* Default thresholds for calendar colorization *) let busy_level1 = ref 2 let busy_level2 = ref 4 let busy_level3 = ref 6 let busy_level4 = ref 8 (* First day of the week? *) let week_starts_monday = ref false (* 12/24 hour time selection *) let schedule_12_hour = ref false let selection_12_hour = ref true let status_12_hour = ref true let description_12_hour = ref true (* Center the schedule on the cursor? *) let center_cursor = ref false (* "jump to" date syntax is big-endian? *) let goto_big_endian = ref true (* "quick add" date syntax uses US conventions? *) let quick_date_US = ref true (* print week numbers? *) let number_weeks = ref false (* home is "sticky"? *) let home_sticky = ref true (* width of calendar/untimed reminder windows *) let untimed_window_width = ref 40 (* trigger advance warning of reminders? *) let advance_warning = ref false (* render untimed reminders in bold? *) let untimed_bold = ref true (* List of included rc files *) let included_rcfiles : (string list) ref = ref [] (* Temporary hash tables for sorting out the color palette *) let color_table = Hashtbl.create 20 let inverse_color_table = Hashtbl.create 20 (* Final hash table that maps from object to color_pair index *) let object_palette = Hashtbl.create 20 (* Turn colors on and off *) let color_on win obj = try let color_index = Hashtbl.find object_palette obj in wattron win (A.color_pair color_index) with Not_found -> () let color_off win obj = try let color_index = Hashtbl.find object_palette obj in wattroff win (A.color_pair color_index) with Not_found -> () let command_of_key key = Hashtbl.find table_key_command key let key_of_command command = Hashtbl.find table_command_key command let entry_of_key key = Hashtbl.find table_key_entry key let key_of_entry entry = Hashtbl.find table_entry_key entry let decode_single_key_string key_string = let decode_alias str = match str with |"" -> 27 |"" -> 9 |"" -> Key.enter |"" -> 10 |"" -> Key.ic |"" -> Key.dc |"" -> Key.home |"" -> Key.end_ |"" -> Key.ppage |"" -> Key.npage |"" -> 32 |"" -> Key.backspace |"" -> Key.left |"" -> Key.right |"" -> Key.up |"" -> Key.down |"" -> (Key.f 1) |"" -> (Key.f 2) |"" -> (Key.f 3) |"" -> (Key.f 4) |"" -> (Key.f 5) |"" -> (Key.f 6) |"" -> (Key.f 7) |"" -> (Key.f 8) |"" -> (Key.f 9) |"" -> (Key.f 10) |"" -> (Key.f 11) |"" -> (Key.f 12) |_ -> if String.length key_string = 1 then int_of_char str.[0] else config_failwith ("Unrecognized key \"" ^ str ^ "\"") in (* This regexp is used to extract the ctrl and meta characters from a string * representing a keypress. * It matches \\M\\C or \\C\\M or \\C or \\M (or no such characters) followed * by an arbitrary string. *) (* Note: is there a way to use raw strings here? Getting tired of those * backslashes...*) let cm_re = Str.regexp "^\\(\\(\\\\M\\\\C\\|\\\\C\\\\M\\)\\|\\(\\\\M\\)\\|\\(\\\\C\\)\\)?\\(<.+>\\|.\\)" in if Str.string_match cm_re key_string 0 then let has_meta_ctrl = try let _ = Str.matched_group 2 key_string in true with Not_found -> false and has_meta = try let _ = Str.matched_group 3 key_string in true with Not_found -> false and has_ctrl = try let _ = Str.matched_group 4 key_string in true with Not_found -> false and main_key = Str.matched_group 5 key_string in if has_meta_ctrl then if String.length main_key = 1 then let uc_main_key = String.uppercase main_key in let mc_chtype = ((int_of_char uc_main_key.[0]) + 64) in let mc_str = "M-C-" ^ uc_main_key in (mc_chtype, mc_str) else config_failwith ("Cannot apply \\\\M\\\\C to key \"" ^ main_key ^ "\";\n" ^ "octal notation might let you accomplish this.") else if has_meta then if String.length main_key = 1 then let m_chtype = ((int_of_char main_key.[0]) + 128) in let m_str = "M-" ^ main_key in (m_chtype, m_str) else config_failwith ("Cannot apply \\\\M to key \"" ^ main_key ^ "\";\n" ^ "octal notation might let you accomplish this.") else if has_ctrl then if String.length main_key = 1 then let uc_main_key = String.uppercase main_key in let c_chtype = ((int_of_char uc_main_key.[0]) - 64) in let c_str = "C-" ^ uc_main_key in (c_chtype, c_str) else config_failwith ("Cannot apply \\\\C to key \"" ^ main_key ^ "\";\n" ^ "octal notation might let you accomplish this.") else let octal_regex = Str.regexp "^0o" in try let _ = Str.search_forward octal_regex key_string 0 in ((int_of_string key_string), ("\\" ^ Str.string_after key_string 2)) with _ -> ((decode_alias main_key), main_key) else config_failwith ("Unable to match binding string with standard regular expression.") (* Register a key binding. This adds hash table entries for translation * between curses chtypes and commands (in both directions). *) let register_binding_internal k k_string op = match op with |CommandOp x -> Hashtbl.add table_key_command k x; Hashtbl.add table_command_key x k_string |EntryOp x -> Hashtbl.add table_key_entry k x; Hashtbl.add table_entry_key x k_string (* convenience routine for previous *) let register_binding key_string op = (* given a string that represents a character, find the associated * curses chtype *) let k, string_rep = decode_single_key_string key_string in register_binding_internal k string_rep op (* unregister a binding *) let unregister_binding key_string = let k, _ = decode_single_key_string key_string in begin try let op = Hashtbl.find table_key_command k in Hashtbl.remove table_key_command k; Hashtbl.remove table_command_key op with Not_found -> () end; begin try let op = Hashtbl.find table_key_entry k in Hashtbl.remove table_key_entry k; Hashtbl.remove table_entry_key op with Not_found -> () end let commands_list = [ ("scroll_up" , CommandOp ScrollUp); ("scroll_down" , CommandOp ScrollDown); ("next_day" , CommandOp NextDay); ("previous_day" , CommandOp PrevDay); ("next_week" , CommandOp NextWeek); ("previous_week" , CommandOp PrevWeek); ("next_month" , CommandOp NextMonth); ("previous_month" , CommandOp PrevMonth); ("home" , CommandOp Home); ("goto" , CommandOp Goto); ("zoom" , CommandOp Zoom); ("edit" , CommandOp Edit); ("edit_any" , CommandOp EditAny); ("copy" , CommandOp CopyReminder); ("cut" , CommandOp CutReminder); ("paste" , CommandOp PasteReminder); ("paste_dialog" , CommandOp PasteReminderDialog); ("scroll_description_up" , CommandOp ScrollDescUp); ("scroll_description_down" , CommandOp ScrollDescDown); ("quick_add" , CommandOp QuickEvent); ("new_timed" , CommandOp NewTimed); ("new_timed_dialog" , CommandOp NewTimedDialog); ("new_untimed" , CommandOp NewUntimed); ("new_untimed_dialog" , CommandOp NewUntimedDialog); ("new_template0" , CommandOp (NewGenReminder 0)); ("new_template0_dialog" , CommandOp (NewGenReminderDialog 0)); ("new_template1" , CommandOp (NewGenReminder 1)); ("new_template1_dialog" , CommandOp (NewGenReminderDialog 1)); ("new_template2" , CommandOp (NewGenReminder 2)); ("new_template2_dialog" , CommandOp (NewGenReminderDialog 2)); ("new_template3" , CommandOp (NewGenReminder 3)); ("new_template3_dialog" , CommandOp (NewGenReminderDialog 3)); ("new_template4" , CommandOp (NewGenReminder 4)); ("new_template4_dialog" , CommandOp (NewGenReminderDialog 4)); ("new_template5" , CommandOp (NewGenReminder 5)); ("new_template5_dialog" , CommandOp (NewGenReminderDialog 5)); ("new_template6" , CommandOp (NewGenReminder 6)); ("new_template6_dialog" , CommandOp (NewGenReminderDialog 6)); ("new_template7" , CommandOp (NewGenReminder 7)); ("new_template7_dialog" , CommandOp (NewGenReminderDialog 7)); ("new_template8" , CommandOp (NewGenReminder 8)); ("new_template8_dialog" , CommandOp (NewGenReminderDialog 8)); ("new_template9" , CommandOp (NewGenReminder 9)); ("new_template9_dialog" , CommandOp (NewGenReminderDialog 9)); ("switch_window" , CommandOp SwitchWindow); ("search_next" , CommandOp SearchNext); ("begin_search" , CommandOp BeginSearch); ("next_reminder" , CommandOp NextReminder); ("view_remind" , CommandOp ViewReminders); ("view_remind_all" , CommandOp ViewAllReminders); ("view_week" , CommandOp ViewWeek); ("view_month" , CommandOp ViewMonth); ("refresh" , CommandOp Refresh ); ("help" , CommandOp ViewKeybindings); ("entry_complete" , EntryOp EntryComplete); ("entry_backspace" , EntryOp EntryBackspace); ("entry_cancel" , EntryOp EntryExit); ("quit" , CommandOp Quit) ] in let create_translation ((commandstr, operation) : string * operation_t) = Hashtbl.add table_commandstr_command commandstr operation; Hashtbl.add table_command_commandstr operation commandstr in List.iter create_translation commands_list (* translate a command string to the command type it represents *) let operation_of_string command_str = Hashtbl.find table_commandstr_command command_str (* translate a command to a string representation *) let string_of_operation op = Hashtbl.find table_command_commandstr op (* Parse a line from a configuration file. This operates on a stream * corresponding to a non-empty line from the file. It will match commands * of the form * bind key command * where 'key' is either a quoted string containing a key specifier or an octal * key representation of the form \xxx (unquoted), and multiple_keys is a quoted * string containing a number of keypresses to simulate. *) let parse_line line_stream = (* Convenience function for 'set' keyword *) let parse_set variable_str variable coersion error = begin match line_stream with parser | [< 'Ident "=" >] -> begin match line_stream with parser | [< 'String ss >] -> begin try variable := coersion ss with _ -> config_failwith (error ^ "\"set " ^ variable_str ^ " = \"") end | [< >] -> config_failwith (error ^ "\"set " ^ variable_str ^ " = \"") end | [< >] -> config_failwith ("Expected \"=\" after \"set " ^ variable_str ^ "\"") end in (* Convenience function for 'color' keyword *) let parse_color obj_str obj = let foreground = begin match line_stream with parser | [< 'Ident "black" >] -> Color.black | [< 'Ident "red" >] -> Color.red | [< 'Ident "green" >] -> Color.green | [< 'Ident "yellow" >] -> Color.yellow | [< 'Ident "blue" >] -> Color.blue | [< 'Ident "magenta" >] -> Color.magenta | [< 'Ident "cyan" >] -> Color.cyan | [< 'Ident "white" >] -> Color.white | [< 'Ident "default" >] -> ~- 1 | [< >] -> config_failwith ("Expected a foreground color after \"set " ^ obj_str) end in let background = begin match line_stream with parser | [< 'Ident "black" >] -> Color.black | [< 'Ident "red" >] -> Color.red | [< 'Ident "green" >] -> Color.green | [< 'Ident "yellow" >] -> Color.yellow | [< 'Ident "blue" >] -> Color.blue | [< 'Ident "magenta" >] -> Color.magenta | [< 'Ident "cyan" >] -> Color.cyan | [< 'Ident "white" >] -> Color.white | [< 'Ident "default" >] -> ~- 1 | [< >] -> config_failwith ("Expected a background color after \"set " ^ obj_str) end in Hashtbl.replace color_table obj (foreground, background) in (* Parsing begins here *) match line_stream with parser | [< 'Kwd "include" >] -> begin match line_stream with parser | [< 'String include_file >] -> included_rcfiles := include_file :: !included_rcfiles | [< >] -> config_failwith ("Expected a filename string after \"include\"") end | [< 'Kwd "bind" >] -> let bind_key key = begin match line_stream with parser | [< 'Ident command_str >] -> begin try let command = operation_of_string command_str in register_binding key command with Not_found -> config_failwith ("Unrecognized command name \"" ^ command_str ^ "\"") end | [< >] -> config_failwith ("Expected a command name after \"bind \"" ^ key ^ "\"") end in begin match line_stream with parser | [< 'String k >] -> bind_key k | [< 'Ident "\\" >] -> begin match line_stream with parser | [< 'Int octal_int >] -> begin try let octal_digits = "0o" ^ (string_of_int octal_int) in bind_key octal_digits with (Failure "int_of_string") -> config_failwith "Expected octal digits after \"\\\"" end | [< >] -> config_failwith "Expected octal digits after \"\\\"" end | [< >] -> config_failwith "Expected a key string after keyword \"bind\"" end | [< 'Kwd "unbind" >] -> begin match line_stream with parser | [< 'String k >] -> unregister_binding k | [< >] -> config_failwith ("Expected a key string after keyword \"unbind\"") end | [< 'Kwd "set" >] -> begin match line_stream with parser | [< 'Ident "remind_command" >] -> parse_set "remind_command" remind_command (fun x -> x) "Expected a command string after " | [< 'Ident "reminders_file" >] -> parse_set "reminders_file" reminders_file (fun x -> x) "Expected a filename string after " | [< 'Ident "edit_old_command" >] -> parse_set "edit_old_command" edit_old_command (fun x -> x) "Expected a command string after " | [< 'Ident "edit_new_command" >] -> parse_set "edit_new_command" edit_new_command (fun x -> x) "Expected a command string after " | [< 'Ident "edit_any_command" >] -> parse_set "edit_any_command" edit_any_command (fun x -> x) "Expected a command string after " | [< 'Ident "timed_template" >] -> parse_set "timed_template" timed_template (fun x -> x) "Expected a template string after " | [< 'Ident "untimed_template" >] -> parse_set "untimed_template" untimed_template (fun x -> x) "Expected a template string after " | [< 'Ident "template0" >] -> parse_set "template0" template0 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template1" >] -> parse_set "template1" template1 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template2" >] -> parse_set "template2" template2 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template3" >] -> parse_set "template3" template3 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template4" >] -> parse_set "template4" template4 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template5" >] -> parse_set "template5" template5 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template6" >] -> parse_set "template6" template6 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template7" >] -> parse_set "template7" template7 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template8" >] -> parse_set "template8" template8 (fun x -> Some x) "Expected a template string after " | [< 'Ident "template9" >] -> parse_set "template9" template9 (fun x -> Some x) "Expected a template string after " | [< 'Ident "busy_algorithm" >] -> parse_set "busy_algorithm" busy_algorithm int_of_string "Expected an integral string after " | [< 'Ident "untimed_duration" >] -> parse_set "untimed_duration" untimed_duration float_of_string "Expected a float string after " | [< 'Ident "busy_level1" >] -> parse_set "busy_level1" busy_level1 int_of_string "Expected an integral string after " | [< 'Ident "busy_level2" >] -> parse_set "busy_level2" busy_level2 int_of_string "Expected an integral string after " | [< 'Ident "busy_level3" >] -> parse_set "busy_level3" busy_level3 int_of_string "Expected an integral string after " | [< 'Ident "busy_level4" >] -> parse_set "busy_level4" busy_level4 int_of_string "Expected an integral string after " | [< 'Ident "week_starts_monday" >] -> parse_set "week_starts_monday" week_starts_monday bool_of_string "Expected a boolean string after " | [< 'Ident "schedule_12_hour" >] -> parse_set "schedule_12_hour" schedule_12_hour bool_of_string "Expected a boolean string after " | [< 'Ident "selection_12_hour" >] -> parse_set "selection_12_hour" selection_12_hour bool_of_string "Expected a boolean string after " | [< 'Ident "status_12_hour" >] -> parse_set "status_12_hour" status_12_hour bool_of_string "Expected a boolean string after " | [< 'Ident "description_12_hour" >] -> parse_set "description_12_hour" description_12_hour bool_of_string "Expected a boolean string after " | [< 'Ident "center_cursor" >] -> parse_set "center_cursor" center_cursor bool_of_string "Expected a boolean string after " | [< 'Ident "goto_big_endian" >] -> parse_set "goto_big_endian" goto_big_endian bool_of_string "Expected a boolean string after " | [< 'Ident "quick_date_US" >] -> parse_set "quick_date_US" quick_date_US bool_of_string "Expected a boolean string after " | [< 'Ident "number_weeks" >] -> parse_set "number_weeks" number_weeks bool_of_string "Expected a boolean string after " | [< 'Ident "home_sticky" >] -> parse_set "home_sticky" home_sticky bool_of_string "Expected a boolean string after " | [< 'Ident "untimed_window_width" >] -> parse_set "untimed_window_width" untimed_window_width int_of_string "Expected an integral string after " | [< 'Ident "advance_warning" >] -> parse_set "advance_warning" advance_warning bool_of_string "Expected a boolean string after " | [< 'Ident "untimed_bold" >] -> parse_set "untimed_bold" untimed_bold bool_of_string "Expected a boolean string after " | [< >] -> config_failwith ("Unmatched variable name after \"set\"") end | [< 'Kwd "color" >] -> begin match line_stream with parser | [< 'Ident "help" >] -> parse_color "help" Help | [< 'Ident "timed_default" >] -> parse_color "timed_default" Timed_default | [< 'Ident "timed_current" >] -> parse_color "timed_current" Timed_current | [< 'Ident "timed_reminder" >] -> config_failwith ("\"timed_reminder\" has been deprecated. Please use \"timed_reminder1\".") | [< 'Ident "untimed_reminder" >] -> parse_color "untimed_reminder" Untimed_reminder | [< 'Ident "timed_date" >] -> parse_color "timed_date" Timed_date | [< 'Ident "selection_info" >] -> parse_color "selection_info" Selection_info | [< 'Ident "description" >] -> parse_color "description" Description | [< 'Ident "status" >] -> parse_color "status" Status | [< 'Ident "calendar_labels" >] -> parse_color "calendar_labels" Calendar_labels | [< 'Ident "calendar_level1" >] -> parse_color "calendar_level1" Calendar_level1 | [< 'Ident "calendar_level2" >] -> parse_color "calendar_level2" Calendar_level2 | [< 'Ident "calendar_level3" >] -> parse_color "calendar_level3" Calendar_level3 | [< 'Ident "calendar_selection" >] -> begin Printf.fprintf stderr "Warning: colorable object \"calendar_selection\" has been "; Printf.fprintf stderr "deprecated.\nPlease remove this reference from the wyrdrc file.\n" end | [< 'Ident "calendar_today" >] -> parse_color "calendar_today" Calendar_today | [< 'Ident "left_divider" >] -> parse_color "left_divider" Left_divider | [< 'Ident "right_divider" >] -> parse_color "right_divider" Right_divider | [< 'Ident "timed_reminder1" >] -> parse_color "timed_reminder1" Timed_reminder1 | [< 'Ident "timed_reminder2" >] -> parse_color "timed_reminder2" Timed_reminder2 | [< 'Ident "timed_reminder3" >] -> parse_color "timed_reminder3" Timed_reminder3 | [< 'Ident "timed_reminder4" >] -> parse_color "timed_reminder4" Timed_reminder4 end | [< 'Kwd "#" >] -> () | [< >] -> config_failwith "Expected a keyword at start of line";; (* try opening the rc file, first looking at $HOME/.wyrdrc, * then looking at $PREFIX/etc/wyrdrc *) let open_rcfile rcfile_op = match rcfile_op with |None -> let home_rcfile = let homedir = Sys.getenv "HOME" in homedir ^ "/.wyrdrc" in let rcfile_fullpath = (* expand out any occurrences of ${prefix} that autoconf * decides to insert *) let prefix_regex = Str.regexp "\\${prefix}" in let expanded_sysconfdir = Str.global_replace prefix_regex Install.prefix Install.sysconfdir in Utility.join_path expanded_sysconfdir "wyrdrc" in begin try (open_in home_rcfile, home_rcfile) with Sys_error error_str -> begin try (open_in rcfile_fullpath, rcfile_fullpath) with Sys_error error_str -> failwith ("Could not open configuration file \"" ^ home_rcfile ^ "\" or \"" ^ rcfile_fullpath ^ "\" .") end end |Some file -> try (Utility.expand_open_in_ascii file, file) with Sys_error error_str -> config_failwith ("Could not open configuration file \"" ^ file ^ "\".") (* validate the color table to make sure that the number of defined colors is legal *) let validate_colors () = (* form a Set of all color pairs, and an inverse mapping from color pair to objects *) let initial_palette = let process_entry key pair colors = Hashtbl.add inverse_color_table pair key; PairSet.add pair colors in Hashtbl.fold process_entry color_table PairSet.empty in (* start killing off color pairs as necessary to fit within color_pairs limit *) let rec reduce_colors palette = if PairSet.cardinal palette > pred (color_pairs ()) then begin (* find and remove the color pair with fewest objects assigned *) let min_objects = ref 100000 and best_pair = ref (-1, -1) in let find_best pair = let obj_list = Hashtbl.find_all inverse_color_table pair in if List.length obj_list < !min_objects then begin min_objects := List.length obj_list; best_pair := pair end else () in PairSet.iter find_best palette; (* the color pair needs to be removed from two hashtables and the palette set *) let obj_list = Hashtbl.find_all inverse_color_table !best_pair in List.iter (Hashtbl.remove color_table) obj_list; Hashtbl.remove inverse_color_table !best_pair; reduce_colors (PairSet.remove !best_pair palette) end else palette in let register_color_pair pair n = assert (init_pair n (fst pair) (snd pair)); let f obj = Hashtbl.add object_palette obj n in List.iter f (Hashtbl.find_all inverse_color_table pair); succ n in let _ = PairSet.fold register_color_pair (reduce_colors initial_palette) 1 in () let rec process_rcfile rcfile_op = let line_lexer line = make_lexer ["include"; "bind"; "unbind"; "set"; "color"; "#"] (Stream.of_string line) in let empty_regexp = Str.regexp "^[\t ]*$" in let config_stream, rcfile_filename = open_rcfile rcfile_op in let line_num = ref 0 in try while true do line_num := succ !line_num; let line_string = input_line config_stream in (* Printf.fprintf stderr "read line %2d: %s\n" !line_num line_string; flush stderr; *) if Str.string_match empty_regexp line_string 0 then (* do nothing on an empty line *) () else try let line_stream = line_lexer line_string in parse_line line_stream; (* process any included rcfiles as they are encountered *) begin match !included_rcfiles with |[] -> () |head :: tail -> included_rcfiles := tail; process_rcfile (Some head) end with |Config_failure s -> (let error_str = Printf.sprintf "Syntax error on line %d of \"%s\": %s" !line_num rcfile_filename s in failwith error_str) |Stream.Failure -> failwith (Printf.sprintf "Syntax error on line %d of \"%s\"" !line_num rcfile_filename) done with End_of_file -> begin close_in config_stream end (* arch-tag: DO_NOT_CHANGE_614115ed-7d1d-4834-bda4-e6cf93ac3fcd *) wyrd-1.4.4/cal.ml0000644000175000017500000001105610757447265012306 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* cal.ml * Because cal(1) cannot be relied upon to be uniform across various operating * systems (sigh), it seemed best to provide a generic calendar layout * algorithm. *) open Utility type t = { title : string; weekdays : string; days : string list; weeknums : string list } (* compute the ISO-8601 week number for the given day *) let weeknum_of_tm day = let (_, normalized_day) = Unix.mktime day in (* iso weeks start on Monday *) let iso_wday = (normalized_day.Unix.tm_wday + 6) mod 7 in (* find Thursday of the same week *) let thurs = {normalized_day with Unix.tm_mday = normalized_day.Unix.tm_mday + 3 - iso_wday } in let (_, normalized_thurs) = Unix.mktime thurs in (* which Thursday of the year is it? *) (normalized_thurs.Unix.tm_yday / 7) + 1 (* Create a Cal.t data structure for the desired timestamp. If * start_monday = true then the first day of the week will be * Monday. *) let make timestamp start_monday = let tm = Unix.localtime timestamp in (* compute the weekday of the first day of the month *) let first_weekday = let temp = {tm with Unix.tm_mday = 1} in let (_, first) = Unix.mktime temp in first.Unix.tm_wday in (* compute the last day of the month *) let last_day = let temp = {tm with Unix.tm_mday = 32} in let (_, nextmonth) = Unix.mktime temp in 32 - nextmonth.Unix.tm_mday in (* generate the title *) let year_s = string_of_int (tm.Unix.tm_year + 1900) in let mon_year = (full_string_of_tm_mon tm.Unix.tm_mon) ^ " " ^ year_s in let pad_len = (20 - (String.length mon_year)) / 2 in let cal_title = (String.make pad_len ' ') ^ mon_year in (* generate the weekday strings *) let rec build_weekdays wkd_str wd_num count = if count > 7 then wkd_str else build_weekdays (wkd_str ^ " " ^ (short_string_of_tm_wday wd_num)) ((succ wd_num) mod 7) (succ count) in let week_start_day = if start_monday then 1 else 0 in let cal_weekdays = build_weekdays (short_string_of_tm_wday week_start_day) ((succ week_start_day) mod 7) 2 in (* generate the days of the month *) let rec build_monthdays weeks_list week_str weeknum_list mday wday = if mday > last_day then let weeknum_str = let last_weekday = {tm with Unix.tm_mday = pred mday} in let weeknum = weeknum_of_tm last_weekday in Printf.sprintf "%2d" weeknum in (List.rev (week_str :: weeks_list), List.rev (weeknum_str :: weeknum_list)) else if wday = week_start_day then let weeknum_str = let last_weekday = {tm with Unix.tm_mday = pred mday} in let weeknum = weeknum_of_tm last_weekday in Printf.sprintf "%2d" weeknum in build_monthdays (week_str :: weeks_list) (Printf.sprintf "%2d" mday) (weeknum_str :: weeknum_list) (succ mday) ((succ wday) mod 7) else build_monthdays weeks_list (week_str ^ (Printf.sprintf " %2d" mday)) weeknum_list (succ mday) ((succ wday) mod 7) in (* create the padding for the first few empty days of the calendar *) let padding = if first_weekday >= week_start_day then String.make ((first_weekday - week_start_day) * 3) ' ' else String.make ((first_weekday + 7 - week_start_day) * 3) ' ' in let (cal_monthdays, cal_weeknums) = build_monthdays [] (padding ^ " 1") [] 2 ((succ first_weekday) mod 7) in { title = cal_title; weekdays = cal_weekdays; days = cal_monthdays; weeknums = cal_weeknums } (* arch-tag: DO_NOT_CHANGE_4909df7f-9801-448d-9030-fb4b0232408d *) wyrd-1.4.4/curses/0000755000175000017500000000000010757447266012517 5ustar paulpaulwyrd-1.4.4/curses/COPYING0000644000175000017500000006347610757447266013572 0ustar paulpaul GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! wyrd-1.4.4/curses/curses.mli0000644000175000017500000005571410757447266014542 0ustar paulpaultype window and screen and terminal and chtype = int and attr_t = int and err = bool module Acs : sig type acs = { ulcorner : chtype; llcorner : chtype; urcorner : chtype; lrcorner : chtype; ltee : chtype; rtee : chtype; btee : chtype; ttee : chtype; hline : chtype; vline : chtype; plus : chtype; s1 : chtype; s9 : chtype; diamond : chtype; ckboard : chtype; degree : chtype; plminus : chtype; bullet : chtype; larrow : chtype; rarrow : chtype; darrow : chtype; uarrow : chtype; board : chtype; lantern : chtype; block : chtype; s3 : chtype; s7 : chtype; lequal : chtype; gequal : chtype; pi : chtype; nequal : chtype; sterling : chtype; } val bssb : acs -> chtype val ssbb : acs -> chtype val bbss : acs -> chtype val sbbs : acs -> chtype val sbss : acs -> chtype val sssb : acs -> chtype val ssbs : acs -> chtype val bsss : acs -> chtype val bsbs : acs -> chtype val sbsb : acs -> chtype val ssss : acs -> chtype end external addch : chtype -> err = "mlcurses_addch" external waddch : window -> chtype -> err = "mlcurses_waddch" external mvaddch : int -> int -> chtype -> err = "mlcurses_mvaddch" external mvwaddch : window -> int -> int -> chtype -> err = "mlcurses_mvwaddch" external echochar : chtype -> err = "mlcurses_echochar" external wechochar : window -> chtype -> err = "mlcurses_wechochar" external addchstr : chtype array -> err = "mlcurses_addchstr" external waddchstr : window -> chtype array -> err = "mlcurses_waddchstr" external mvaddchstr : int -> int -> chtype array -> err = "mlcurses_mvaddchstr" external mvwaddchstr : window -> int -> int -> chtype array -> err = "mlcurses_mvwaddchstr" external addchnstr : chtype array -> int -> int -> err = "mlcurses_addchnstr" external waddchnstr : window -> chtype array -> int -> int -> err = "mlcurses_waddchnstr" external mvaddchnstr : int -> int -> chtype array -> int -> int -> err = "mlcurses_mvaddchnstr" external mvwaddchnstr : window -> int -> int -> chtype array -> int -> int -> err = "mlcurses_mvwaddchnstr_bytecode" "mlcurses_mvwaddchnstr_native" external addstr : string -> err = "mlcurses_addstr" external waddstr : window -> string -> err = "mlcurses_waddstr" external mvaddstr : int -> int -> string -> err = "mlcurses_mvaddstr" external mvwaddstr : window -> int -> int -> string -> err = "mlcurses_mvwaddstr" external addnstr : string -> int -> int -> err = "mlcurses_addnstr" external waddnstr : window -> string -> int -> int -> err = "mlcurses_waddnstr" external mvaddnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvaddnstr" external mvwaddnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwaddnstr_bytecode" "mlcurses_mvwaddnstr_native" external attroff : int -> unit = "mlcurses_attroff" external wattroff : window -> int -> unit = "mlcurses_wattroff" external attron : int -> unit = "mlcurses_attron" external wattron : window -> int -> unit = "mlcurses_wattron" external attrset : int -> unit = "mlcurses_attrset" external wattrset : window -> int -> unit = "mlcurses_wattrset" external standend : unit -> unit = "mlcurses_standend" external wstandend : window -> unit = "mlcurses_wstandend" external standout : unit -> unit = "mlcurses_standout" external wstandout : window -> unit = "mlcurses_wstandout" external attr_off : attr_t -> unit = "mlcurses_attr_off" external wattr_off : window -> attr_t -> unit = "mlcurses_wattr_off" external attr_on : attr_t -> unit = "mlcurses_attr_on" external wattr_on : window -> attr_t -> unit = "mlcurses_wattr_on" external attr_set : attr_t -> int -> unit = "mlcurses_attr_set" external wattr_set : window -> attr_t -> int -> unit = "mlcurses_wattr_set" external chgat : int -> attr_t -> int -> unit = "mlcurses_chgat" external wchgat : window -> int -> attr_t -> int -> unit = "mlcurses_wchgat" external mvchgat : int -> int -> int -> attr_t -> int -> unit = "mlcurses_mvchgat" external mvwchgat : window -> int -> int -> int -> attr_t -> int -> unit = "mlcurses_mvwchgat_bytecode" "mlcurses_mvwchgat_native" external beep : unit -> err = "mlcurses_beep" external flash : unit -> err = "mlcurses_flash" external bkgdset : chtype -> unit = "mlcurses_bkgdset" external wbkgdset : window -> chtype -> unit = "mlcurses_wbkgdset" external bkgd : chtype -> unit = "mlcurses_bkgd" external wbkgd : window -> chtype -> unit = "mlcurses_wbkgd" external getbkgd : window -> chtype = "mlcurses_getbkgd" external border : chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> unit = "mlcurses_border_bytecode" "mlcurses_border_native" external wborder : window -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> unit = "mlcurses_wborder_bytecode" "mlcurses_wborder_native" external box : window -> chtype -> chtype -> unit = "mlcurses_box" external hline : chtype -> int -> unit = "mlcurses_hline" external whline : window -> chtype -> int -> unit = "mlcurses_whline" external vline : chtype -> int -> unit = "mlcurses_vline" external wvline : window -> chtype -> int -> unit = "mlcurses_wvline" external mvhline : int -> int -> chtype -> int -> unit = "mlcurses_mvhline" external mvwhline : window -> int -> int -> chtype -> int -> unit = "mlcurses_mvwhline" external mvvline : int -> int -> chtype -> int -> unit = "mlcurses_mvvline" external mvwvline : window -> int -> int -> chtype -> int -> unit = "mlcurses_mvwvline" external erase : unit -> unit = "mlcurses_erase" external werase : window -> unit = "mlcurses_werase" external clear : unit -> unit = "mlcurses_clear" external wclear : window -> unit = "mlcurses_wclear" external clrtobot : unit -> unit = "mlcurses_clrtobot" external wclrtobot : window -> unit = "mlcurses_wclrtobot" external clrtoeol : unit -> unit = "mlcurses_clrtoeol" external wclrtoeol : window -> unit = "mlcurses_wclrtoeol" external start_color : unit -> err = "mlcurses_start_color" external use_default_colors : unit -> err = "mlcurses_use_default_colors" external init_pair : int -> int -> int -> err = "mlcurses_init_pair" external init_color : int -> int -> int -> int -> err = "mlcurses_init_color" external has_colors : unit -> bool = "mlcurses_has_colors" external can_change_color : unit -> bool = "mlcurses_can_change_color" external color_content : int -> int * int * int = "mlcurses_color_content" external pair_content : int -> int * int = "mlcurses_pair_content" external colors : unit -> int = "mlcurses_colors" external color_pairs : unit -> int = "mlcurses_color_pairs" external delch : unit -> err = "mlcurses_delch" external wdelch : window -> err = "mlcurses_wdelch" external mvdelch : int -> int -> err = "mlcurses_mvdelch" external mvwdelch : window -> int -> int -> err = "mlcurses_mvwdelch" external deleteln : unit -> err = "mlcurses_deleteln" external wdeleteln : window -> err = "mlcurses_wdeleteln" external insdelln : int -> err = "mlcurses_insdelln" external winsdelln : window -> int -> err = "mlcurses_winsdelln" external insertln : unit -> err = "mlcurses_insertln" external winsertln : window -> err = "mlcurses_winsertln" external getch : unit -> int = "mlcurses_getch" external wgetch : window -> int = "mlcurses_wgetch" external mvgetch : int -> int -> int = "mlcurses_mvgetch" external mvwgetch : window -> int -> int -> int = "mlcurses_mvwgetch" external ungetch : int -> err = "mlcurses_ungetch" external getstr : string -> err = "mlcurses_getstr" external wgetstr : window -> string -> err = "mlcurses_wgetstr" external mvgetstr : int -> int -> string -> err = "mlcurses_mvgetstr" external mvwgetstr : window -> int -> int -> string -> err = "mlcurses_mvwgetstr" external getnstr : string -> int -> int -> err = "mlcurses_getnstr" external wgetnstr : window -> string -> int -> int -> err = "mlcurses_wgetnstr" external mvgetnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvgetnstr" external mvwgetnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwgetnstr_bytecode" "mlcurses_mvwgetnstr_native" external getyx : window -> int * int = "mlcurses_getyx" external getparyx : window -> int * int = "mlcurses_getparyx" external getbegyx : window -> int * int = "mlcurses_getbegyx" external getmaxyx : window -> int * int = "mlcurses_getmaxyx" external inch : unit -> chtype = "mlcurses_inch" external winch : window -> chtype = "mlcurses_winch" external mvinch : int -> int -> chtype = "mlcurses_mvinch" external mvwinch : window -> int -> int -> chtype = "mlcurses_mvwinch" external inchstr : chtype array -> err = "mlcurses_inchstr" external winchstr : window -> chtype array -> err = "mlcurses_winchstr" external mvinchstr : int -> int -> chtype array -> err = "mlcurses_mvinchstr" external mvwinchstr : window -> int -> int -> chtype array -> err = "mlcurses_mvwinchstr" external inchnstr : chtype array -> int -> int -> err = "mlcurses_inchnstr" external winchnstr : window -> chtype array -> int -> int -> err = "mlcurses_winchnstr" external mvinchnstr : int -> int -> chtype array -> int -> int -> err = "mlcurses_mvinchnstr" external mvwinchnstr : window -> int -> int -> chtype array -> int -> int -> err = "mlcurses_mvwinchnstr_bytecode" "mlcurses_mvwinchnstr_native" external insch : chtype -> err = "mlcurses_insch" external winsch : window -> chtype -> err = "mlcurses_winsch" external mvinsch : int -> int -> chtype -> err = "mlcurses_mvinsch" external mvwinsch : window -> int -> int -> chtype -> err = "mlcurses_mvwinsch" external initscr : unit -> window = "mlcurses_initscr" external endwin : unit -> unit = "mlcurses_endwin" external isendwin : unit -> bool = "mlcurses_isendwin" external newterm : string -> Unix.file_descr -> Unix.file_descr -> screen = "mlcurses_newterm" external set_term : screen -> unit = "mlcurses_set_term" external delscreen : screen -> unit = "mlcurses_delscreen" external stdscr : unit -> window = "mlcurses_stdscr" external insstr : string -> err = "mlcurses_insstr" external winsstr : window -> string -> err = "mlcurses_winsstr" external mvinsstr : int -> int -> string -> err = "mlcurses_mvinsstr" external mvwinsstr : window -> int -> int -> string -> err = "mlcurses_mvwinsstr" external insnstr : string -> int -> int -> err = "mlcurses_insnstr" external winsnstr : window -> string -> int -> int -> err = "mlcurses_winsnstr" external mvinsnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvinsnstr" external mvwinsnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwinsnstr_bytecode" "mlcurses_mvwinsnstr_native" external instr : string -> err = "mlcurses_instr" external winstr : window -> string -> err = "mlcurses_winstr" external mvinstr : int -> int -> string -> err = "mlcurses_mvinstr" external mvwinstr : window -> int -> int -> string -> err = "mlcurses_mvwinstr" external innstr : string -> int -> int -> err = "mlcurses_innstr" external winnstr : window -> string -> int -> int -> err = "mlcurses_winnstr" external mvinnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvinnstr" external mvwinnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwinnstr_bytecode" "mlcurses_mvwinnstr_native" external cbreak : unit -> err = "mlcurses_cbreak" external nocbreak : unit -> err = "mlcurses_nocbreak" external echo : unit -> err = "mlcurses_echo" external noecho : unit -> err = "mlcurses_noecho" external halfdelay : int -> err = "mlcurses_halfdelay" external intrflush : window -> bool -> err = "mlcurses_intrflush" external keypad : window -> bool -> err = "mlcurses_keypad" external meta : window -> bool -> err = "mlcurses_meta" external nodelay : window -> bool -> err = "mlcurses_nodelay" external raw : unit -> err = "mlcurses_raw" external noraw : unit -> err = "mlcurses_noraw" external noqiflush : unit -> unit = "mlcurses_noqiflush" external qiflush : unit -> unit = "mlcurses_qiflush" external notimeout : window -> bool -> err = "mlcurses_notimeout" external timeout : int -> unit = "mlcurses_timeout" external wtimeout : window -> int -> unit = "mlcurses_wtimeout" external typeahead : Unix.file_descr -> err = "mlcurses_typeahead" external notypeahead : unit -> err = "mlcurses_notypeahead" external def_prog_mode : unit -> unit = "mlcurses_def_prog_mode" external def_shell_mode : unit -> unit = "mlcurses_def_shell_mode" external reset_prog_mode : unit -> unit = "mlcurses_reset_prog_mode" external reset_shell_mode : unit -> unit = "mlcurses_reset_shell_mode" external resetty : unit -> unit = "mlcurses_resetty" external savetty : unit -> unit = "mlcurses_savetty" external getsyx : unit -> int * int = "mlcurses_getsyx" external setsyx : int -> int -> unit = "mlcurses_setsyx" external curs_set : int -> err = "mlcurses_curs_set" external napms : int -> unit = "mlcurses_napms" external ripoffline : bool -> unit = "mlcurses_ripoffline" external get_ripoff : unit -> window * int = "mlcurses_get_ripoff" external mousemask : int -> int * int = "mlcurses_mousemask" external move : int -> int -> err = "mlcurses_move" external wmove : window -> int -> int -> err = "mlcurses_wmove" external clearok : window -> bool -> unit = "mlcurses_clearok" external idlok : window -> bool -> unit = "mlcurses_idlok" external idcok : window -> bool -> unit = "mlcurses_idcok" external immedok : window -> bool -> unit = "mlcurses_immedok" external leaveok : window -> bool -> unit = "mlcurses_leaveok" external setscrreg : int -> int -> err = "mlcurses_setscrreg" external wsetscrreg : window -> int -> int -> err = "mlcurses_wsetscrreg" external scrollok : window -> bool -> unit = "mlcurses_scrollok" external nl : unit -> unit = "mlcurses_nl" external nonl : unit -> unit = "mlcurses_nonl" external overlay : window -> window -> err = "mlcurses_overlay" external overwrite : window -> window -> err = "mlcurses_overwrite" external copywin : window -> window -> int -> int -> int -> int -> int -> int -> bool -> err = "mlcurses_copywin_bytecode" "mlcurses_copywin_native" external newpad : int -> int -> window = "mlcurses_newpad" external subpad : window -> int -> int -> int -> int -> window = "mlcurses_subpad" external prefresh : window -> int -> int -> int -> int -> int -> int -> err = "mlcurses_prefresh_bytecode" "mlcurses_prefresh_native" external pnoutrefresh : window -> int -> int -> int -> int -> int -> int -> err = "mlcurses_pnoutrefresh_bytecode" "mlcurses_pnoutrefresh_native" external pechochar : window -> chtype -> err = "mlcurses_pechochar" external refresh : unit -> err = "mlcurses_refresh" external wrefresh : window -> err = "mlcurses_wrefresh" external wnoutrefresh : window -> err = "mlcurses_wnoutrefresh" external doupdate : unit -> err = "mlcurses_doupdate" external redrawwin : window -> err = "mlcurses_redrawwin" external wredrawln : window -> int -> int -> err = "mlcurses_wredrawln" external wresize : window -> int -> int -> err = "mlcurses_wresize" external resizeterm : int -> int -> err = "mlcurses_resizeterm" external scr_dump : string -> err = "mlcurses_scr_dump" external scr_restore : string -> err = "mlcurses_scr_restore" external scr_init : string -> err = "mlcurses_scr_init" external scr_set : string -> err = "mlcurses_scr_set" external scroll : window -> err = "mlcurses_scroll" external scrl : int -> err = "mlcurses_scrl" external wscrl : window -> int -> err = "mlcurses_wscrl" external slk_init : int -> err = "mlcurses_slk_init" external slk_set : int -> string -> int -> err = "mlcurses_slk_set" external slk_refresh : unit -> err = "mlcurses_slk_refresh" external slk_noutrefresh : unit -> err = "mlcurses_slk_noutrefresh" external slk_label : int -> string = "mlcurses_slk_label" external slk_clear : unit -> err = "mlcurses_slk_clear" external slk_restore : unit -> err = "mlcurses_slk_restore" external slk_touch : unit -> err = "mlcurses_slk_touch" external slk_attron : attr_t -> err = "mlcurses_slk_attron" external slk_attroff : attr_t -> err = "mlcurses_slk_attroff" external slk_attrset : attr_t -> err = "mlcurses_slk_attrset" external baudrate : unit -> int = "mlcurses_baudrate" external erasechar : unit -> char = "mlcurses_erasechar" external has_ic : unit -> bool = "mlcurses_has_ic" external has_il : unit -> bool = "mlcurses_has_il" external killchar : unit -> char = "mlcurses_killchar" external longname : unit -> string = "mlcurses_longname" external termattrs : unit -> attr_t = "mlcurses_termattrs" external termname : unit -> string = "mlcurses_termname" external tgetent : string -> bool = "mlcurses_tgetent" external tgetflag : string -> bool = "mlcurses_tgetflag" external tgetnum : string -> int = "mlcurses_tgetnum" external tgetstr : string -> bool = "mlcurses_tgetstr" external tgoto : string -> int -> int -> string = "mlcurses_tgoto" external setupterm : string -> Unix.file_descr -> err = "mlcurses_setupterm" external setterm : string -> err = "mlcurses_setterm" external cur_term : unit -> terminal = "mlcurses_cur_term" external set_curterm : terminal -> terminal = "mlcurses_set_curterm" external del_curterm : terminal -> err = "mlcurses_del_curterm" external restartterm : string -> Unix.file_descr -> err = "mlcurses_restartterm" external putp : string -> err = "mlcurses_putp" external vidattr : chtype -> err = "mlcurses_vidattr" external mvcur : int -> int -> int -> int -> err = "mlcurses_mvcur" external tigetflag : string -> bool = "mlcurses_tigetflag" external tigetnum : string -> int = "mlcurses_tigetnum" external tigetstr : string -> string = "mlcurses_tigetstr" external tputs : string -> int -> (char -> unit) -> err = "mlcurses_tputs" external vidputs : chtype -> (char -> unit) -> err = "mlcurses_vidputs" external tparm : string -> int array -> string = "mlcurses_tparm" external bool_terminfo_variable : int -> string * string * string = "mlcurses_bool_terminfo_variable" external num_terminfo_variable : int -> string * string * string = "mlcurses_num_terminfo_variable" external str_terminfo_variable : int -> string * string * string = "mlcurses_str_terminfo_variable" external touchwin : window -> err = "mlcurses_touchwin" external touchline : window -> int -> int -> err = "mlcurses_touchline" external untouchwin : window -> err = "mlcurses_untouchwin" external wtouchln : window -> int -> int -> bool -> err = "mlcurses_wtouchln" external is_linetouched : window -> int -> int = "mlcurses_is_linetouched" external is_wintouched : window -> bool = "mlcurses_is_wintouched" external unctrl : chtype -> string = "mlcurses_unctrl" external keyname : int -> string = "mlcurses_keyname" external filter : unit -> unit = "mlcurses_filter" external use_env : bool -> unit = "mlcurses_use_env" external putwin : window -> Unix.file_descr -> err = "mlcurses_putwin" external getwin : Unix.file_descr -> window = "mlcurses_getwin" external delay_output : int -> err = "mlcurses_delay_output" external flushinp : unit -> unit = "mlcurses_flushinp" external newwin : int -> int -> int -> int -> window = "mlcurses_newwin" external delwin : window -> err = "mlcurses_delwin" external mvwin : window -> int -> int -> err = "mlcurses_mvwin" external subwin : window -> int -> int -> int -> int -> window = "mlcurses_subwin" external derwin : window -> int -> int -> int -> int -> window = "mlcurses_derwin" external mvderwin : window -> int -> int -> err = "mlcurses_mvderwin" external dupwin : window -> window = "mlcurses_dupwin" external wsyncup : window -> unit = "mlcurses_wsyncup" external syncok : window -> bool -> err = "mlcurses_syncok" external wcursyncup : window -> unit = "mlcurses_wcursyncup" external wsyncdown : window -> unit = "mlcurses_wsyncdown" external get_acs_codes : unit -> Acs.acs = "mlcurses_get_acs_codes" external winch_handler_on : unit -> unit = "mlcurses_winch_handler_on" external winch_handler_off : unit -> unit = "mlcurses_winch_handler_off" external get_size : unit -> int * int = "mlcurses_get_size" external get_size_fd : Unix.file_descr -> int * int = "mlcurses_get_size_fd" val null_window : window val bool_terminfo_variables : (string, string * string) Hashtbl.t val num_terminfo_variables : (string, string * string) Hashtbl.t val str_terminfo_variables : (string, string * string) Hashtbl.t module A : sig val normal : int val attributes : int val chartext : int val color : int val standout : int val underline : int val reverse : int val blink : int val dim : int val bold : int val altcharset : int val invis : int val protect : int val horizontal : int val left : int val low : int val right : int val top : int val vertical : int val combine : int list -> int val color_pair : int -> int val pair_number : int -> int end module WA : sig val normal : int val attributes : int val chartext : int val color : int val standout : int val underline : int val reverse : int val blink : int val dim : int val bold : int val altcharset : int val invis : int val protect : int val horizontal : int val left : int val low : int val right : int val top : int val vertical : int val combine : int list -> int val color_pair : int -> int val pair_number : int -> int end module Color : sig val black : int val red : int val green : int val yellow : int val blue : int val magenta : int val cyan : int val white : int end module Key : sig val code_yes : int val min : int val break : int val down : int val up : int val left : int val right : int val home : int val backspace : int val f0 : int val dl : int val il : int val dc : int val ic : int val eic : int val clear : int val eos : int val eol : int val sf : int val sr : int val npage : int val ppage : int val stab : int val ctab : int val catab : int val enter : int val sreset : int val reset : int val print : int val ll : int val a1 : int val a3 : int val b2 : int val c1 : int val c3 : int val btab : int val beg : int val cancel : int val close : int val command : int val copy : int val create : int val end_ : int val exit : int val find : int val help : int val mark : int val message : int val move : int val next : int val open_ : int val options : int val previous : int val redo : int val reference : int val refresh : int val replace : int val restart : int val resume : int val save : int val sbeg : int val scancel : int val scommand : int val scopy : int val screate : int val sdc : int val sdl : int val select : int val send : int val seol : int val sexit : int val sfind : int val shelp : int val shome : int val sic : int val sleft : int val smessage : int val smove : int val snext : int val soptions : int val sprevious : int val sprint : int val sredo : int val sreplace : int val sright : int val srsume : int val ssave : int val ssuspend : int val sundo : int val suspend : int val undo : int val mouse : int val resize : int val max : int val f : int -> int end wyrd-1.4.4/curses/functions.c.in0000644000175000017500000004473510757447266015315 0ustar paulpaul/* addch */ ML1(addch,err,chtype) ML2(waddch,err,window,chtype) ML3(mvaddch,err,int,int,chtype) ML4(mvwaddch,err,window,int,int,chtype) ML1(echochar,err,chtype) ML2(wechochar,err,window,chtype) /* addchstr */ #define copie(l,id,ar) int i,c=l,r; \ chtype *t=malloc((c+1)*sizeof(chtype)); \ if(t==NULL) failwith("Out of memory"); \ for(i=0;i0); END ML1(tigetnum,int,string) ML1d(tigetstr,string,string) BEG1 char *s=tigetstr(a_string(aa)); if((s==NULL)||(s==(char * )-1)) failwith("tigetstr"); CAMLreturn(copy_string(s)); END ML3d(tputs,err,string,int,(char->unit)) BEG3 putc_function=ac; r_err(tputs(a_string(aa),a_int(ab),putc_callback)); END ML2d(vidputs,err,chtype,(char->unit)) BEG2 putc_function=ab; r_err(vidputs(a_chtype(aa),putc_callback)); END ML2d(tparm,string,string,int array) BEG2 int t[10],i,n=Wosize_val(ab); if(n>10) n=10; for(i=0;i #include #include #include #include #include #include #ifdef CURSES_HEADER #include CURSES_HEADER #else #ifdef HAVE_NCURSES_H #include #else #include #endif #endif #include /* Du travail pour les esclaves de M$ */ #include #include #include #define AWB(x) caml__dummy_##x=caml__dummy_##x; /* anti-warning bugware */ #define r_unit(f) f; CAMLreturn(Val_unit); #define r_window(f) CAMLreturn((value)f) #define r_terminal(f) CAMLreturn((value)f) #define r_err(f) CAMLreturn(Val_bool((f)!=ERR)) #define r_int(f) CAMLreturn(Val_int(f)) #define r_char(f) CAMLreturn(Val_int((f)&255)) #define r_chtype(f) CAMLreturn(Val_int(f)) #define r_attr_t(f) CAMLreturn(Val_int(f)) #define r_bool(f) CAMLreturn(Val_bool(f)) #define r_int_int(x,y) \ { CAMLlocal1(ret); AWB(ret); \ ret=alloc_tuple(2); \ Store_field(ret,0,Val_int(x)); \ Store_field(ret,1,Val_int(y)); \ CAMLreturn(ret); } #define r_int_int_int(x,y,z) \ { CAMLlocal1(ret); AWB(ret); \ ret=alloc_tuple(3); \ Store_field(ret,0,Val_int(x)); \ Store_field(ret,1,Val_int(y)); \ Store_field(ret,2,Val_int(z)); \ CAMLreturn(ret); } #define r_string(f) \ { char *ret=f; \ if(ret==NULL) failwith("Null pointer"); \ CAMLreturn(copy_string(ret)); } #define a_window(a) ((WINDOW * )a) #define a_terminal(a) ((TERMINAL * )a) #define a_screen(a) ((SCREEN * )Field(a,2)) #define a_int(a) Int_val(a) #define a_bool(a) Bool_val(a) #define a_chtype(a) Int_val(a) #define a_attr_t(a) Int_val(a) #define a_string(a) String_val(a) #define RA0 CAMLparam0(); #define RA1 CAMLparam1(aa); AWB(aa); #define RA2 CAMLparam2(aa,ab); AWB(aa); #define RA3 CAMLparam3(aa,ab,ac); AWB(aa); #define RA4 CAMLparam4(aa,ab,ac,ad); AWB(aa); #define RA5 CAMLparam5(aa,ab,ac,ad,ae); AWB(aa); #define RA6 CAMLparam5(aa,ab,ac,ad,ae); CAMLxparam1(af); AWB(aa); AWB(af); #define RA7 CAMLparam5(aa,ab,ac,ad,ae); CAMLxparam2(af,ag); AWB(aa); AWB(af); #define RA8 CAMLparam5(aa,ab,ac,ad,ae); CAMLxparam3(af,ag,ah); AWB(aa); AWB(af); #define RA9 CAMLparam5(aa,ab,ac,ad,ae); CAMLxparam4(af,ag,ah,ai); AWB(aa); AWB(af); #define ML0(f,tr) \ value mlcurses_##f(void) \ { RA0 r_##tr(f()); } #define ML1(f,tr,ta) \ value mlcurses_##f(value aa) \ { RA1 r_##tr(f(a_##ta(aa))); } #define ML2(f,tr,ta,tb) \ value mlcurses_##f(value aa,value ab) \ { RA2 r_##tr(f(a_##ta(aa),a_##tb(ab))); } #define ML3(f,tr,ta,tb,tc) \ value mlcurses_##f(value aa,value ab,value ac) \ { RA3 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac))); } #define ML4(f,tr,ta,tb,tc,td) \ value mlcurses_##f(value aa,value ab,value ac,value ad) \ { RA4 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac),a_##td(ad))); } #define ML5(f,tr,ta,tb,tc,td,te) \ value mlcurses_##f(value aa,value ab,value ac,value ad,value ae) \ { RA5 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac),a_##td(ad),a_##te(ae))); } #define ML7(f,tr,ta,tb,tc,td,te,tf,tg) \ value mlcurses_##f##_bytecode(value *a,int n) \ { RA0 r_##tr(f(a_##ta(a[0]),a_##tb(a[1]),a_##tc(a[2]),a_##td(a[3]), \ a_##te(a[4]),a_##tf(a[5]),a_##tg(a[6]))); } \ value mlcurses_##f##_native(value aa,value ab,value ac,value ad, \ value ae,value af,value ag) \ { RA7 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac),a_##td(ad), \ a_##te(ae),a_##tf(af),a_##tg(ag))); } #define ML8(f,tr,ta,tb,tc,td,te,tf,tg,th) \ value mlcurses_##f##_bytecode(value *a,int n) \ { RA0 r_##tr(f(a_##ta(a[0]),a_##tb(a[1]),a_##tc(a[2]),a_##td(a[3]), \ a_##te(a[4]),a_##tf(a[5]),a_##tg(a[6]),a_##th(a[7]))); } \ value mlcurses_##f##_native(value aa,value ab,value ac,value ad, \ value ae,value af,value ag,value ah) \ { RA8 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac),a_##td(ad), \ a_##te(ae),a_##tf(af),a_##tg(ag),a_##th(ah))); } #define ML9(f,tr,ta,tb,tc,td,te,tf,tg,th,ti) \ value mlcurses_##f##_bytecode(value *a,int n) \ { RA0 r_##tr(f(a_##ta(a[0]),a_##tb(a[1]),a_##tc(a[2]),a_##td(a[3]),a_##te(a[4]), \ a_##tf(a[5]),a_##tg(a[6]),a_##th(a[7]),a_##ti(a[8]))); } \ value mlcurses_##f##_native(value aa,value ab,value ac,value ad,value ae, \ value af,value ag,value ah,value ai) \ { RA9 r_##tr(f(a_##ta(aa),a_##tb(ab),a_##tc(ac),a_##td(ad),a_##te(ae), \ a_##tf(af),a_##tg(ag),a_##th(ah),a_##ti(ai))); } #define ML0d(f,tr) value mlcurses_##f(void) #define ML1d(f,tr,ta) value mlcurses_##f(value aa) #define ML2d(f,tr,ta,tb) value mlcurses_##f(value aa,value ab) #define ML3d(f,tr,ta,tb,tc) value mlcurses_##f(value aa,value ab,value ac) #define ML4d(f,tr,ta,tb,tc,td) value mlcurses_##f(value aa,value ab,\ value ac,value ad) #define ML5d(f,tr,ta,tb,tc,td,te) value mlcurses_##f(value aa,value ab,\ value ac,value ad,value ae) #define ML6d(f,tr,ta,tb,tc,td,te,tf) value mlcurses_##f##_native(value,value,\ value,value,value,value); \ value mlcurses_##f##_bytecode(value *a,int n) \ { return(mlcurses_##f##_native(a[0],a[1],a[2],a[3],a[4],a[5])); } \ value mlcurses_##f##_native(value aa,value ab,value ac,value ad,value ae,value af) #define BEG0 { RA0 { #define BEG1 { RA1 { #define BEG2 { RA2 { #define BEG3 { RA3 { #define BEG4 { RA4 { #define BEG5 { RA5 { #define BEG6 { RA6 { #define BEG7 { RA7 { #define BEG8 { RA8 { #define BEG9 { RA9 { #define END }} static WINDOW *ripoff_w[5]; static int ripoff_l[5]; static int ripoff_niv=0; static int ripoff_callback(WINDOW *w,int l) { if(ripoff_niv==5) return(0); ripoff_w[ripoff_niv]=w; ripoff_l[ripoff_niv]=l; ripoff_niv++; return(0); } value putc_function; static int putc_callback(int c) { CAMLparam0(); CAMLlocal1(ret); AWB(ret); ret=callback_exn(putc_function,Val_int(c&255)); CAMLreturn(Is_exception_result(ret)?-1:0); } /* Du travail pour les esclaves de M$ */ static void winch_handler(int n) { signal(n,winch_handler); ungetch(KEY_RESIZE); } #include "functions.c" #include "caml/signals.h" /* The following routines were rewritten 07/14/04 by Paul Pelzl * to allow other threads to run while getch() is blocking */ value mlcurses_getch(void) { CAMLparam0(); int ch; enter_blocking_section(); ch = getch(); leave_blocking_section(); CAMLreturn(Val_int(ch)); } value mlcurses_wgetch(value win) { CAMLparam1(win); int ch; WINDOW* w; caml__dummy_win = caml__dummy_win; w = (WINDOW *) win; enter_blocking_section(); ch = wgetch(w); leave_blocking_section(); CAMLreturn(Val_int(ch)); } wyrd-1.4.4/curses/test.ml0000644000175000017500000000416710757447266014040 0ustar paulpaulopen Curses let () = ripoffline true let w = initscr () let (wd, ncol) = get_ripoff () (*let () = assert (start_color ()) let () = assert (init_pair 1 Color.red Color.white)*) let () = assert (cbreak ()) let () = assert (noecho ()) let () = assert (intrflush w false) let () = assert (keypad w true) let () = for i = 0 to 10 do assert (mvaddch i (i * 2) (A.color_pair 1 + 111)) done let () = border 0 0 0 0 0 0 0 0 let () = wborder w 0 0 0 0 0 0 0 0 let () = assert (refresh ()) let (c1, c2) = mousemask (-1) let () = assert (mvaddstr 3 1 "Bonjour") let () = assert (mvaddstr 4 2 (string_of_int c1)) let () = assert (mvaddstr 5 2 (string_of_int c2)) let t = Array.init 50 (fun x -> 64 + x) let () = assert (addchnstr t 10 3) let () = assert (mvaddnstr 8 40 "Bonjour" 1 3) let () = assert (mvinsstr 8 40 "toto ") let t = [|0; 0; 0; 0 |] let () = assert (inchnstr t 0 3) let () = winch_handler_on () let kup = tigetstr "kcuu1" let () = assert (addstr kup) let acs = get_acs_codes () let () = assert (addch acs.Acs.ulcorner) let i = getch () let (nc, np, can) = (colors (), color_pairs (), can_change_color ()) let (c1, c2) = pair_content 1 let l = ref [] let () = assert (tputs "totoping" 1 (fun c -> l := (int_of_char c) :: !l)) let (tr, tc) = get_size () let () = endwin () let () = Array.iter (fun x -> print_int x; print_newline ()) t let () = print_string "key="; print_int i; print_newline () let () = print_int tr; print_string " "; print_int tc; print_newline () let () = print_int nc; print_string " " let () = print_int np; print_string " " let () = print_string (if can then "oui" else "non"); print_newline () let () = print_int c1; print_string " " let () = print_int c2; print_newline () let () = print_int ncol; print_newline () let () = List.iter (fun x -> print_int x; print_string " ") !l; print_newline () (*let i = ref 0 let () = while let (a, b, c) = str_terminfo_variable !i in (a <> "") && (print_string (a ^ "\t" ^ b ^ "\t" ^ c); print_newline (); true) do i := !i + 1 done*) (*let () = Hashtbl.iter (fun a (b,c) -> print_string (a ^ "\t" ^ b ^ "\t" ^ c); print_newline ()) str_terminfo_variables*) wyrd-1.4.4/curses/functions.c0000644000175000017500000004777310757447266014715 0ustar paulpaul ML1(addch,err,chtype) ML2(waddch,err,window,chtype) ML3(mvaddch,err,int,int,chtype) ML4(mvwaddch,err,window,int,int,chtype) ML1(echochar,err,chtype) ML2(wechochar,err,window,chtype) ML1d(addchstr,err,chtype array) BEG1 int i,c=Wosize_val(aa),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i0); END ML1(tigetnum,int,string) ML1d(tigetstr,string,string) BEG1 char *s=tigetstr(a_string(aa)); if((s==NULL)||(s==(char * )-1)) failwith("tigetstr"); CAMLreturn(copy_string(s)); END ML3d(tputs,err,string,int,(char->unit)) BEG3 putc_function=ac; r_err(tputs(a_string(aa),a_int(ab),putc_callback)); END ML2d(vidputs,err,chtype,(char->unit)) BEG2 putc_function=ab; r_err(vidputs(a_chtype(aa),putc_callback)); END ML2d(tparm,string,string,int array) BEG2 int t[10],i,n=Wosize_val(ab); if(n>10) n=10; for(i=0;i err = "mlcurses_addch" external waddch : window -> chtype -> err = "mlcurses_waddch" external mvaddch : int -> int -> chtype -> err = "mlcurses_mvaddch" external mvwaddch : window -> int -> int -> chtype -> err = "mlcurses_mvwaddch" external echochar : chtype -> err = "mlcurses_echochar" external wechochar : window -> chtype -> err = "mlcurses_wechochar" external addchstr : chtype array -> err = "mlcurses_addchstr" (* int i,c=Wosize_val(aa),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i chtype array -> err = "mlcurses_waddchstr" (* int i,c=Wosize_val(ab),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i int -> chtype array -> err = "mlcurses_mvaddchstr" (* int i,c=Wosize_val(ac),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i int -> int -> chtype array -> err = "mlcurses_mvwaddchstr" (* int i,c=Wosize_val(ad),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i int -> int -> err = "mlcurses_addchnstr" (* int i0=Int_val(ab); int i,c=Int_val(ac),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i chtype array -> int -> int -> err = "mlcurses_waddchnstr" (* int i0=Int_val(ac); int i,c=Int_val(ad),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i int -> chtype array -> int -> int -> err = "mlcurses_mvaddchnstr" (* int i0=Int_val(ad); int i,c=Int_val(ae),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i int -> int -> chtype array -> int -> int -> err = "mlcurses_mvwaddchnstr_bytecode" "mlcurses_mvwaddchnstr_native" (* int i0=Int_val(ae); int i,c=Int_val(af),r; chtype *t=malloc((c+1)*sizeof(chtype)); if(t==NULL) failwith("Out of memory"); for(i=0;i err = "mlcurses_addstr" external waddstr : window -> string -> err = "mlcurses_waddstr" external mvaddstr : int -> int -> string -> err = "mlcurses_mvaddstr" external mvwaddstr : window -> int -> int -> string -> err = "mlcurses_mvwaddstr" external addnstr : string -> int -> int -> err = "mlcurses_addnstr" (* r_err(addnstr(a_string(aa)+a_int(ab),a_int(ac))); *) external waddnstr : window -> string -> int -> int -> err = "mlcurses_waddnstr" (* r_err(waddnstr(a_window(aa),a_string(ab)+a_int(ac),a_int(ad))); *) external mvaddnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvaddnstr" (* r_err(mvaddnstr(a_int(aa),a_int(ab), a_string(ac)+a_int(ad),a_int(ae))); *) external mvwaddnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwaddnstr_bytecode" "mlcurses_mvwaddnstr_native" (* r_err(mvwaddnstr(a_window(aa),a_int(ab),a_int(ac), a_string(ad)+a_int(ae),a_int(af))); *) external attroff : int -> unit = "mlcurses_attroff" external wattroff : window -> int -> unit = "mlcurses_wattroff" external attron : int -> unit = "mlcurses_attron" external wattron : window -> int -> unit = "mlcurses_wattron" external attrset : int -> unit = "mlcurses_attrset" external wattrset : window -> int -> unit = "mlcurses_wattrset" external standend : unit -> unit = "mlcurses_standend" external wstandend : window -> unit = "mlcurses_wstandend" external standout : unit -> unit = "mlcurses_standout" external wstandout : window -> unit = "mlcurses_wstandout" external attr_off : attr_t -> unit = "mlcurses_attr_off" (* attr_off(a_attr_t(aa),NULL); CAMLreturn(Val_unit); *) external wattr_off : window -> attr_t -> unit = "mlcurses_wattr_off" (* wattr_off(a_window(aa),a_attr_t(ab),NULL); CAMLreturn(Val_unit); *) external attr_on : attr_t -> unit = "mlcurses_attr_on" (* attr_on(a_attr_t(aa),NULL); CAMLreturn(Val_unit); *) external wattr_on : window -> attr_t -> unit = "mlcurses_wattr_on" (* wattr_on(a_window(aa),a_attr_t(ab),NULL); CAMLreturn(Val_unit); *) external attr_set : attr_t -> int -> unit = "mlcurses_attr_set" (* attr_set(a_attr_t(aa),a_int(ab),NULL); CAMLreturn(Val_unit); *) external wattr_set : window -> attr_t -> int -> unit = "mlcurses_wattr_set" (* wattr_set(a_window(aa),a_attr_t(ab),a_int(ac),NULL); CAMLreturn(Val_unit); *) external chgat : int -> attr_t -> int -> unit = "mlcurses_chgat" (* chgat(a_int(aa),a_attr_t(ab),a_int(ac),NULL); CAMLreturn(Val_unit); *) external wchgat : window -> int -> attr_t -> int -> unit = "mlcurses_wchgat" (* wchgat(a_window(aa),a_int(ab),a_attr_t(ac),a_int(ad),NULL); CAMLreturn(Val_unit); *) external mvchgat : int -> int -> int -> attr_t -> int -> unit = "mlcurses_mvchgat" (* mvchgat(a_int(aa),a_int(ab),a_int(ac),a_attr_t(ad),a_int(ae),NULL); CAMLreturn(Val_unit); *) external mvwchgat : window -> int -> int -> int -> attr_t -> int -> unit = "mlcurses_mvwchgat_bytecode" "mlcurses_mvwchgat_native" (* mvwchgat(a_window(aa),a_int(ab),a_int(ac),a_int(ad),a_attr_t(ae), a_int(af),NULL); CAMLreturn(Val_unit); *) external beep : unit -> err = "mlcurses_beep" external flash : unit -> err = "mlcurses_flash" external bkgdset : chtype -> unit = "mlcurses_bkgdset" external wbkgdset : window -> chtype -> unit = "mlcurses_wbkgdset" external bkgd : chtype -> unit = "mlcurses_bkgd" external wbkgd : window -> chtype -> unit = "mlcurses_wbkgd" external getbkgd : window -> chtype = "mlcurses_getbkgd" external border : chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> unit = "mlcurses_border_bytecode" "mlcurses_border_native" external wborder : window -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> chtype -> unit = "mlcurses_wborder_bytecode" "mlcurses_wborder_native" external box : window -> chtype -> chtype -> unit = "mlcurses_box" external hline : chtype -> int -> unit = "mlcurses_hline" external whline : window -> chtype -> int -> unit = "mlcurses_whline" external vline : chtype -> int -> unit = "mlcurses_vline" external wvline : window -> chtype -> int -> unit = "mlcurses_wvline" external mvhline : int -> int -> chtype -> int -> unit = "mlcurses_mvhline" external mvwhline : window -> int -> int -> chtype -> int -> unit = "mlcurses_mvwhline" external mvvline : int -> int -> chtype -> int -> unit = "mlcurses_mvvline" external mvwvline : window -> int -> int -> chtype -> int -> unit = "mlcurses_mvwvline" external erase : unit -> unit = "mlcurses_erase" external werase : window -> unit = "mlcurses_werase" external clear : unit -> unit = "mlcurses_clear" external wclear : window -> unit = "mlcurses_wclear" external clrtobot : unit -> unit = "mlcurses_clrtobot" external wclrtobot : window -> unit = "mlcurses_wclrtobot" external clrtoeol : unit -> unit = "mlcurses_clrtoeol" external wclrtoeol : window -> unit = "mlcurses_wclrtoeol" external start_color : unit -> err = "mlcurses_start_color" external init_pair : int -> int -> int -> err = "mlcurses_init_pair" external init_color : int -> int -> int -> int -> err = "mlcurses_init_color" external has_colors : unit -> bool = "mlcurses_has_colors" external can_change_color : unit -> bool = "mlcurses_can_change_color" external color_content : int -> int*int*int = "mlcurses_color_content" (* short x,y,z; if(color_content(Int_val(aa),&x,&y,&z)==ERR) x=y=z=-1; r_int_int_int(x,y,z); *) external pair_content : int -> int*int = "mlcurses_pair_content" (* short x,y; if(pair_content(Int_val(aa),&y,&x)==ERR) x=y=-1; r_int_int(x,y); *) external colors : unit -> int = "mlcurses_colors" (* r_int(COLORS); *) external color_pairs : unit -> int = "mlcurses_color_pairs" (* r_int(COLOR_PAIRS); *) external use_default_colors : unit -> err = "mlcurses_use_default_colors" external delch : unit -> err = "mlcurses_delch" external wdelch : window -> err = "mlcurses_wdelch" external mvdelch : int -> int -> err = "mlcurses_mvdelch" external mvwdelch : window -> int -> int -> err = "mlcurses_mvwdelch" external deleteln : unit -> err = "mlcurses_deleteln" external wdeleteln : window -> err = "mlcurses_wdeleteln" external insdelln : int -> err = "mlcurses_insdelln" external winsdelln : window -> int -> err = "mlcurses_winsdelln" external insertln : unit -> err = "mlcurses_insertln" external winsertln : window -> err = "mlcurses_winsertln" external mvgetch : int -> int -> int = "mlcurses_mvgetch" external mvwgetch : window -> int -> int -> int = "mlcurses_mvwgetch" external ungetch : int -> err = "mlcurses_ungetch" external getstr : string -> err = "mlcurses_getstr" (* r_err(getnstr(a_string(aa),string_length(aa))); *) external wgetstr : window -> string -> err = "mlcurses_wgetstr" (* r_err(wgetnstr(a_window(aa),a_string(ab),string_length(ab))); *) external mvgetstr : int -> int -> string -> err = "mlcurses_mvgetstr" (* r_err(mvgetnstr(a_int(aa),a_int(ab),a_string(ac),string_length(ac))); *) external mvwgetstr : window -> int -> int -> string -> err = "mlcurses_mvwgetstr" (* r_err(mvwgetnstr(a_window(aa),a_int(ab),a_int(ac),a_string(ad), string_length(ad))); *) external getnstr : string -> int -> int -> err = "mlcurses_getnstr" (* r_err(getnstr(a_string(aa)+a_int(ab),a_int(ac))); *) external wgetnstr : window -> string -> int -> int -> err = "mlcurses_wgetnstr" (* r_err(wgetnstr(a_window(aa),a_string(ab)+a_int(ac),a_int(ad))); *) external mvgetnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvgetnstr" (* r_err(mvgetnstr(a_int(aa),a_int(ab),a_string(ac)+a_int(ad), a_int(ae))); *) external mvwgetnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwgetnstr_bytecode" "mlcurses_mvwgetnstr_native" (* r_err(mvwgetnstr(a_window(aa),a_int(ab),a_int(ac),a_string(ad)+a_int(ae), a_int(af))); *) external getyx : window -> int*int = "mlcurses_getyx" (* int x,y; getyx(a_window(aa),y,x); r_int_int(x,y); *) external getparyx : window -> int*int = "mlcurses_getparyx" (* int x,y; getparyx(a_window(aa),y,x); r_int_int(x,y); *) external getbegyx : window -> int*int = "mlcurses_getbegyx" (* int x,y; getbegyx(a_window(aa),y,x); r_int_int(x,y); *) external getmaxyx : window -> int*int = "mlcurses_getmaxyx" (* int x,y; getmaxyx(a_window(aa),y,x); r_int_int(x,y); *) external inch : unit -> chtype = "mlcurses_inch" external winch : window -> chtype = "mlcurses_winch" external mvinch : int -> int -> chtype = "mlcurses_mvinch" external mvwinch : window -> int -> int -> chtype = "mlcurses_mvwinch" external inchstr : chtype array -> err = "mlcurses_inchstr" (* int i,ne=Wosize_val(aa); chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=inchnstr(tbl,ne); for(i=0;i chtype array -> err = "mlcurses_winchstr" (* int i,ne=Wosize_val(ab); chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=winchnstr(a_window(aa),tbl,ne); for(i=0;i int -> chtype array -> err = "mlcurses_mvinchstr" (* int i,ne=Wosize_val(ac); chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=mvinchnstr(a_int(aa),a_int(ab),tbl,ne); for(i=0;i int -> int -> chtype array -> err = "mlcurses_mvwinchstr" (* int i,ne=Wosize_val(ad); chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=mvwinchnstr(a_window(aa),a_int(ab),a_int(ac),tbl,ne); for(i=0;i int -> int -> err = "mlcurses_inchnstr" (* int i0=a_int(ab); int i,ne=Wosize_val(aa)-i0; chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=inchnstr(tbl,a_int(ac)); for(i=0;i chtype array -> int -> int -> err = "mlcurses_winchnstr" (* int i0=a_int(ac); int i,ne=Wosize_val(ab)-i0; chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=winchnstr(a_window(aa),tbl,a_int(ad)); for(i=0;i int -> chtype array -> int -> int -> err = "mlcurses_mvinchnstr" (* int i0=a_int(ad); int i,ne=Wosize_val(ac)-i0; chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=mvinchnstr(a_int(aa),a_int(ab),tbl,a_int(ae)); for(i=0;i int -> int -> chtype array -> int -> int -> err = "mlcurses_mvwinchnstr_bytecode" "mlcurses_mvwinchnstr_native" (* int i0=a_int(ae); int i,ne=Wosize_val(ad)-i0; chtype *tbl=malloc((ne+1)*sizeof(chtype)); int ret=mvwinchnstr(a_window(aa),a_int(ab),a_int(ac),tbl,a_int(af)); for(i=0;i err = "mlcurses_insch" external winsch : window -> chtype -> err = "mlcurses_winsch" external mvinsch : int -> int -> chtype -> err = "mlcurses_mvinsch" external mvwinsch : window -> int -> int -> chtype -> err = "mlcurses_mvwinsch" external initscr : unit -> window = "mlcurses_initscr" external endwin : unit -> unit = "mlcurses_endwin" external isendwin : unit -> bool = "mlcurses_isendwin" external newterm : string -> Unix.file_descr -> Unix.file_descr -> screen = "mlcurses_newterm" (* CAMLlocal1(r); int fda=dup(a_int(ab)),fdb=dup(a_int(ac)); FILE *fa=fdopen(fda,"w"),*fb=fdopen(fdb,"r"); SCREEN *s; AWB(r); r=alloc_tuple(3); Store_field(r,0,Val_int(fa)); Store_field(r,1,Val_int(fb)); s=newterm(a_string(aa),fa,fb); if(s==NULL){ fclose(fa); fclose(fb); failwith("newterm"); } Store_field(r,2,(value)s); CAMLreturn(r); *) external set_term : screen -> unit = "mlcurses_set_term" external delscreen : screen -> unit = "mlcurses_delscreen" (* delscreen(a_screen(aa)); fclose((FILE * )Field(aa,0)); fclose((FILE * )Field(aa,1)); CAMLreturn(Val_unit); *) external stdscr : unit -> window = "mlcurses_stdscr" (* r_window(stdscr); *) external null_window : unit -> window = "mlcurses_null_window" (* r_window(NULL); *) external insstr : string -> err = "mlcurses_insstr" (* r_err(insnstr(a_string(aa),string_length(aa))); *) external winsstr : window -> string -> err = "mlcurses_winsstr" (* r_err(winsnstr(a_window(aa),a_string(ab),string_length(ab))); *) external mvinsstr : int -> int -> string -> err = "mlcurses_mvinsstr" (* r_err(mvinsnstr(a_int(aa),a_int(ab),a_string(ac),string_length(ac))); *) external mvwinsstr : window -> int -> int -> string -> err = "mlcurses_mvwinsstr" (* r_err(mvwinsnstr(a_window(aa),a_int(ab),a_int(ac), a_string(ad),string_length(ad))); *) external insnstr : string -> int -> int -> err = "mlcurses_insnstr" (* r_err(insnstr(a_string(aa)+a_int(ab),a_int(ac))); *) external winsnstr : window -> string -> int -> int -> err = "mlcurses_winsnstr" (* r_err(winsnstr(a_window(aa),a_string(ab)+a_int(ac),a_int(ad))); *) external mvinsnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvinsnstr" (* r_err(mvinsnstr(a_int(aa),a_int(ab),a_string(ac)+a_int(ad),a_int(ae))); *) external mvwinsnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwinsnstr_bytecode" "mlcurses_mvwinsnstr_native" (* r_err(mvwinsnstr(a_window(aa),a_int(ab),a_int(ac), a_string(ad)+a_int(ae),a_int(af))); *) external instr : string -> err = "mlcurses_instr" (* r_err(innstr(a_string(aa),string_length(aa))); *) external winstr : window -> string -> err = "mlcurses_winstr" (* r_err(winnstr(a_window(aa),a_string(ab),string_length(ab))); *) external mvinstr : int -> int -> string -> err = "mlcurses_mvinstr" (* r_err(mvinnstr(a_int(aa),a_int(ab),a_string(ac),string_length(ac))); *) external mvwinstr : window -> int -> int -> string -> err = "mlcurses_mvwinstr" (* r_err(mvwinnstr(a_window(aa),a_int(ab),a_int(ac), a_string(ad),string_length(ad))); *) external innstr : string -> int -> int -> err = "mlcurses_innstr" (* r_err(innstr(a_string(aa)+a_int(ab),a_int(ac))); *) external winnstr : window -> string -> int -> int -> err = "mlcurses_winnstr" (* r_err(winnstr(a_window(aa),a_string(ab)+a_int(ac),a_int(ad))); *) external mvinnstr : int -> int -> string -> int -> int -> err = "mlcurses_mvinnstr" (* r_err(mvinnstr(a_int(aa),a_int(ab),a_string(ac)+a_int(ad),a_int(ae))); *) external mvwinnstr : window -> int -> int -> string -> int -> int -> err = "mlcurses_mvwinnstr_bytecode" "mlcurses_mvwinnstr_native" (* r_err(mvwinnstr(a_window(aa),a_int(ab),a_int(ac), a_string(ad)+a_int(ae),a_int(af))); *) external cbreak : unit -> err = "mlcurses_cbreak" external nocbreak : unit -> err = "mlcurses_nocbreak" external echo : unit -> err = "mlcurses_echo" external noecho : unit -> err = "mlcurses_noecho" external halfdelay : int -> err = "mlcurses_halfdelay" external intrflush : window -> bool -> err = "mlcurses_intrflush" external keypad : window -> bool -> err = "mlcurses_keypad" external meta : window -> bool -> err = "mlcurses_meta" external nodelay : window -> bool -> err = "mlcurses_nodelay" external raw : unit -> err = "mlcurses_raw" external noraw : unit -> err = "mlcurses_noraw" external noqiflush : unit -> unit = "mlcurses_noqiflush" external qiflush : unit -> unit = "mlcurses_qiflush" external notimeout : window -> bool -> err = "mlcurses_notimeout" external timeout : int -> unit = "mlcurses_timeout" external wtimeout : window -> int -> unit = "mlcurses_wtimeout" external typeahead : Unix.file_descr -> err = "mlcurses_typeahead" (* r_err(typeahead(a_int(aa))); *) external notypeahead : unit -> err = "mlcurses_notypeahead" (* r_err(typeahead(-1)); *) external def_prog_mode : unit -> unit = "mlcurses_def_prog_mode" external def_shell_mode : unit -> unit = "mlcurses_def_shell_mode" external reset_prog_mode : unit -> unit = "mlcurses_reset_prog_mode" external reset_shell_mode : unit -> unit = "mlcurses_reset_shell_mode" external resetty : unit -> unit = "mlcurses_resetty" external savetty : unit -> unit = "mlcurses_savetty" external getsyx : unit -> int*int = "mlcurses_getsyx" (* int x,y; getsyx(y,x); r_int_int(x,y); *) external setsyx : int -> int -> unit = "mlcurses_setsyx" external curs_set : int -> err = "mlcurses_curs_set" external napms : int -> unit = "mlcurses_napms" external ripoffline : bool -> unit = "mlcurses_ripoffline" (* ripoffline(Bool_val(aa)?1:-1,ripoff_callback); CAMLreturn(Val_unit); *) external get_ripoff : unit -> window*int = "mlcurses_get_ripoff" (* if(ripoff_niv==0) failwith("get_ripoff"); ripoff_niv--; r_int_int(ripoff_w[ripoff_niv],ripoff_l[ripoff_niv]); *) external mousemask : int -> int*int = "mlcurses_mousemask" (* mmask_t r=1234,n=Int_val(aa); n=mousemask(n,&r); r_int_int(n,r); *) external move : int -> int -> err = "mlcurses_move" external wmove : window -> int -> int -> err = "mlcurses_wmove" external clearok : window -> bool -> unit = "mlcurses_clearok" external idlok : window -> bool -> unit = "mlcurses_idlok" external idcok : window -> bool -> unit = "mlcurses_idcok" external immedok : window -> bool -> unit = "mlcurses_immedok" external leaveok : window -> bool -> unit = "mlcurses_leaveok" external setscrreg : int -> int -> err = "mlcurses_setscrreg" external wsetscrreg : window -> int -> int -> err = "mlcurses_wsetscrreg" external scrollok : window -> bool -> unit = "mlcurses_scrollok" external nl : unit -> unit = "mlcurses_nl" external nonl : unit -> unit = "mlcurses_nonl" external overlay : window -> window -> err = "mlcurses_overlay" external overwrite : window -> window -> err = "mlcurses_overwrite" external copywin : window -> window -> int -> int -> int -> int -> int -> int -> bool -> err = "mlcurses_copywin_bytecode" "mlcurses_copywin_native" external newpad : int -> int -> window = "mlcurses_newpad" external subpad : window -> int -> int -> int -> int -> window = "mlcurses_subpad" external prefresh : window -> int -> int -> int -> int -> int -> int -> err = "mlcurses_prefresh_bytecode" "mlcurses_prefresh_native" external pnoutrefresh : window -> int -> int -> int -> int -> int -> int -> err = "mlcurses_pnoutrefresh_bytecode" "mlcurses_pnoutrefresh_native" external pechochar : window -> chtype -> err = "mlcurses_pechochar" external refresh : unit -> err = "mlcurses_refresh" external wrefresh : window -> err = "mlcurses_wrefresh" external wnoutrefresh : window -> err = "mlcurses_wnoutrefresh" external doupdate : unit -> err = "mlcurses_doupdate" external redrawwin : window -> err = "mlcurses_redrawwin" external wredrawln : window -> int -> int -> err = "mlcurses_wredrawln" external wresize : window -> int -> int -> err = "mlcurses_wresize" external resizeterm : int -> int -> err = "mlcurses_resizeterm" external scr_dump : string -> err = "mlcurses_scr_dump" external scr_restore : string -> err = "mlcurses_scr_restore" external scr_init : string -> err = "mlcurses_scr_init" external scr_set : string -> err = "mlcurses_scr_set" external scroll : window -> err = "mlcurses_scroll" external scrl : int -> err = "mlcurses_scrl" external wscrl : window -> int -> err = "mlcurses_wscrl" external slk_init : int -> err = "mlcurses_slk_init" external slk_set : int -> string -> int -> err = "mlcurses_slk_set" external slk_refresh : unit -> err = "mlcurses_slk_refresh" external slk_noutrefresh : unit -> err = "mlcurses_slk_noutrefresh" external slk_label : int -> string = "mlcurses_slk_label" external slk_clear : unit -> err = "mlcurses_slk_clear" external slk_restore : unit -> err = "mlcurses_slk_restore" external slk_touch : unit -> err = "mlcurses_slk_touch" external slk_attron : attr_t -> err = "mlcurses_slk_attron" external slk_attroff : attr_t -> err = "mlcurses_slk_attroff" external slk_attrset : attr_t -> err = "mlcurses_slk_attrset" external baudrate : unit -> int = "mlcurses_baudrate" external erasechar : unit -> char = "mlcurses_erasechar" external has_ic : unit -> bool = "mlcurses_has_ic" external has_il : unit -> bool = "mlcurses_has_il" external killchar : unit -> char = "mlcurses_killchar" external longname : unit -> string = "mlcurses_longname" external termattrs : unit -> attr_t = "mlcurses_termattrs" external termname : unit -> string = "mlcurses_termname" external tgetent : string -> bool = "mlcurses_tgetent" (* CAMLreturn(Val_bool(tgetent(NULL,String_val(aa))==1)); *) external tgetflag : string -> bool = "mlcurses_tgetflag" external tgetnum : string -> int = "mlcurses_tgetnum" external tgetstr : string -> bool = "mlcurses_tgetstr" (* r_string(tgetstr(String_val(aa),NULL)); *) external tgoto : string -> int -> int -> string = "mlcurses_tgoto" external setupterm : string -> Unix.file_descr -> err = "mlcurses_setupterm" (* int r; r_err(setupterm(a_string(aa),a_int(ab),&r)); *) external setterm : string -> err = "mlcurses_setterm" external cur_term : unit -> terminal = "mlcurses_cur_term" (* r_terminal(cur_term); *) external set_curterm : terminal -> terminal = "mlcurses_set_curterm" external del_curterm : terminal -> err = "mlcurses_del_curterm" external restartterm : string -> Unix.file_descr -> err = "mlcurses_restartterm" (* int r; r_err(restartterm(a_string(aa),a_int(ab),&r)); *) external putp : string -> err = "mlcurses_putp" external vidattr : chtype -> err = "mlcurses_vidattr" external mvcur : int -> int -> int -> int -> err = "mlcurses_mvcur" external tigetflag : string -> bool = "mlcurses_tigetflag" (* r_bool(tigetflag(a_string(aa))>0); *) external tigetnum : string -> int = "mlcurses_tigetnum" external tigetstr : string -> string = "mlcurses_tigetstr" (* char *s=tigetstr(a_string(aa)); if((s==NULL)||(s==(char * )-1)) failwith("tigetstr"); CAMLreturn(copy_string(s)); *) external tputs : string -> int -> (char->unit) -> err = "mlcurses_tputs" (* putc_function=ac; r_err(tputs(a_string(aa),a_int(ab),putc_callback)); *) external vidputs : chtype -> (char->unit) -> err = "mlcurses_vidputs" (* putc_function=ab; r_err(vidputs(a_chtype(aa),putc_callback)); *) external tparm : string -> int array -> string = "mlcurses_tparm" (* int t[10],i,n=Wosize_val(ab); if(n>10) n=10; for(i=0;i string*string*string = "mlcurses_bool_terminfo_variable" (* CAMLlocal1(s); int n=a_int(aa); AWB(s) s=alloc_tuple(3); Store_field(s,0,Val_unit); Store_field(s,1,Val_unit); Store_field(s,2,Val_unit); if((boolnames[n]==NULL)||(boolcodes[n]==NULL)||(boolfnames[n]==NULL)){ CAMLlocal1(ns); AWB(ns) ns=copy_string(""); Store_field(s,0,ns); Store_field(s,1,ns); Store_field(s,2,ns); }else{ Store_field(s,0,copy_string(boolnames[n])); Store_field(s,1,copy_string(boolcodes[n])); Store_field(s,2,copy_string(boolfnames[n])); } CAMLreturn(s); *) external num_terminfo_variable : int -> string*string*string = "mlcurses_num_terminfo_variable" (* CAMLlocal1(s); int n=a_int(aa); AWB(s) s=alloc_tuple(3); Store_field(s,0,Val_unit); Store_field(s,1,Val_unit); Store_field(s,2,Val_unit); if((numnames[n]==NULL)||(numcodes[n]==NULL)||(numfnames[n]==NULL)){ CAMLlocal1(ns); AWB(ns) ns=copy_string(""); Store_field(s,0,ns); Store_field(s,1,ns); Store_field(s,2,ns); }else{ Store_field(s,0,copy_string(numnames[n])); Store_field(s,1,copy_string(numcodes[n])); Store_field(s,2,copy_string(numfnames[n])); } CAMLreturn(s); *) external str_terminfo_variable : int -> string*string*string = "mlcurses_str_terminfo_variable" (* CAMLlocal1(s); int n=a_int(aa); AWB(s) s=alloc_tuple(3); Store_field(s,0,Val_unit); Store_field(s,1,Val_unit); Store_field(s,2,Val_unit); if((strnames[n]==NULL)||(strcodes[n]==NULL)||(strfnames[n]==NULL)){ CAMLlocal1(ns); AWB(ns) ns=copy_string(""); Store_field(s,0,ns); Store_field(s,1,ns); Store_field(s,2,ns); }else{ Store_field(s,0,copy_string(strnames[n])); Store_field(s,1,copy_string(strcodes[n])); Store_field(s,2,copy_string(strfnames[n])); } CAMLreturn(s); *) external touchwin : window -> err = "mlcurses_touchwin" external touchline : window -> int -> int -> err = "mlcurses_touchline" external untouchwin : window -> err = "mlcurses_untouchwin" external wtouchln : window -> int -> int -> bool -> err = "mlcurses_wtouchln" external is_linetouched : window -> int -> int = "mlcurses_is_linetouched" external is_wintouched : window -> bool = "mlcurses_is_wintouched" external unctrl : chtype -> string = "mlcurses_unctrl" external keyname : int -> string = "mlcurses_keyname" external filter : unit -> unit = "mlcurses_filter" external use_env : bool -> unit = "mlcurses_use_env" external putwin : window -> Unix.file_descr -> err = "mlcurses_putwin" (* int fd=dup(a_int(ab)); FILE *f=fdopen(fd,"w"); int r=putwin(a_window(aa),f); fclose(f); r_err(r); *) external getwin : Unix.file_descr -> window = "mlcurses_getwin" (* int fd=dup(a_int(aa)); FILE *f=fdopen(fd,"r"); int r=putwin(a_window(aa),f); fclose(f); r_err(r); *) external delay_output : int -> err = "mlcurses_delay_output" external flushinp : unit -> unit = "mlcurses_flushinp" external newwin : int -> int -> int -> int -> window = "mlcurses_newwin" external delwin : window -> err = "mlcurses_delwin" external mvwin : window -> int -> int -> err = "mlcurses_mvwin" external subwin : window -> int -> int -> int -> int -> window = "mlcurses_subwin" external derwin : window -> int -> int -> int -> int -> window = "mlcurses_derwin" external mvderwin : window -> int -> int -> err = "mlcurses_mvderwin" external dupwin : window -> window = "mlcurses_dupwin" external wsyncup : window -> unit = "mlcurses_wsyncup" external syncok : window -> bool -> err = "mlcurses_syncok" external wcursyncup : window -> unit = "mlcurses_wcursyncup" external wsyncdown : window -> unit = "mlcurses_wsyncdown" external get_acs_codes : unit -> Acs.acs = "mlcurses_get_acs_codes" (* CAMLlocal1(tr); AWB(tr) tr=alloc_tuple(32); Store_field(tr,0,Val_int(ACS_ULCORNER)); Store_field(tr,1,Val_int(ACS_LLCORNER)); Store_field(tr,2,Val_int(ACS_URCORNER)); Store_field(tr,3,Val_int(ACS_LRCORNER)); Store_field(tr,4,Val_int(ACS_LTEE)); Store_field(tr,5,Val_int(ACS_RTEE)); Store_field(tr,6,Val_int(ACS_BTEE)); Store_field(tr,7,Val_int(ACS_TTEE)); Store_field(tr,8,Val_int(ACS_HLINE)); Store_field(tr,9,Val_int(ACS_VLINE)); Store_field(tr,10,Val_int(ACS_PLUS)); Store_field(tr,11,Val_int(ACS_S1)); Store_field(tr,12,Val_int(ACS_S9)); Store_field(tr,13,Val_int(ACS_DIAMOND)); Store_field(tr,14,Val_int(ACS_CKBOARD)); Store_field(tr,15,Val_int(ACS_DEGREE)); Store_field(tr,16,Val_int(ACS_PLMINUS)); Store_field(tr,17,Val_int(ACS_BULLET)); Store_field(tr,18,Val_int(ACS_LARROW)); Store_field(tr,19,Val_int(ACS_RARROW)); Store_field(tr,20,Val_int(ACS_DARROW)); Store_field(tr,21,Val_int(ACS_UARROW)); Store_field(tr,22,Val_int(ACS_BOARD)); Store_field(tr,23,Val_int(ACS_LANTERN)); Store_field(tr,24,Val_int(ACS_BLOCK)); Store_field(tr,25,Val_int(ACS_S3)); Store_field(tr,26,Val_int(ACS_S7)); Store_field(tr,27,Val_int(ACS_LEQUAL)); Store_field(tr,28,Val_int(ACS_GEQUAL)); Store_field(tr,29,Val_int(ACS_PI)); Store_field(tr,30,Val_int(ACS_NEQUAL)); Store_field(tr,31,Val_int(ACS_STERLING)); CAMLreturn(tr); *) external winch_handler_on : unit -> unit = "mlcurses_winch_handler_on" (* signal(SIGWINCH,winch_handler); CAMLreturn(Val_unit); *) external winch_handler_off : unit -> unit = "mlcurses_winch_handler_off" (* signal(SIGWINCH,SIG_IGN); CAMLreturn(Val_unit); *) external get_size : unit -> int*int = "mlcurses_get_size" (* struct winsize ws; ioctl(0,TIOCGWINSZ,&ws); r_int_int(ws.ws_row,ws.ws_col); *) external get_size_fd : Unix.file_descr -> int*int = "mlcurses_get_size_fd" (* struct winsize ws; ioctl(a_int(aa),TIOCGWINSZ,&ws); r_int_int(ws.ws_row,ws.ws_col); *) (* these two were written separately in ml_curses.c, * to permit proper threading behavior *) external getch : unit -> int = "mlcurses_getch" external wgetch : window -> int = "mlcurses_wgetch" let null_window = null_window () let bool_terminfo_variables = Hashtbl.create 67 let num_terminfo_variables = Hashtbl.create 67 let str_terminfo_variables = Hashtbl.create 601 let () = let rec ins f h n = let (a, b, c) = f n in if a = "" then () else ( Hashtbl.add h c (a, b); ins f h (n + 1) ) in ins bool_terminfo_variable bool_terminfo_variables 0; ins num_terminfo_variable num_terminfo_variables 0; ins str_terminfo_variable str_terminfo_variables 0 module A = struct let normal = 0 let attributes = 0x7FFFFF00 let chartext = 0x000000FF let color = 0x0000FF00 let standout = 0x00010000 let underline = 0x00020000 let reverse = 0x00040000 let blink = 0x00080000 let dim = 0x00100000 let bold = 0x00200000 let altcharset = 0x00400000 let invis = 0x00800000 let protect = 0x01000000 let horizontal = 0x02000000 let left = 0x04000000 let low = 0x08000000 let right = 0x10000000 let top = 0x20000000 let vertical = 0x40000000 let combine = List.fold_left (lor) 0 let color_pair n = (n lsl 8) land color let pair_number a = (a land color) lsr 8 end (* *) module WA = A module Color = struct let black = 0 let red = 1 let green = 2 let yellow = 3 let blue = 4 let magenta = 5 let cyan = 6 let white = 7 end module Key = struct let code_yes = 0o400 let min = 0o401 let break = 0o401 let down = 0o402 let up = 0o403 let left = 0o404 let right = 0o405 let home = 0o406 let backspace = 0o407 let f0 = 0o410 let dl = 0o510 let il = 0o511 let dc = 0o512 let ic = 0o513 let eic = 0o514 let clear = 0o515 let eos = 0o516 let eol = 0o517 let sf = 0o520 let sr = 0o521 let npage = 0o522 let ppage = 0o523 let stab = 0o524 let ctab = 0o525 let catab = 0o526 let enter = 0o527 let sreset = 0o530 let reset = 0o531 let print = 0o532 let ll = 0o533 let a1 = 0o534 let a3 = 0o535 let b2 = 0o536 let c1 = 0o537 let c3 = 0o540 let btab = 0o541 let beg = 0o542 let cancel = 0o543 let close = 0o544 let command = 0o545 let copy = 0o546 let create = 0o547 let end_ = 0o550 let exit = 0o551 let find = 0o552 let help = 0o553 let mark = 0o554 let message = 0o555 let move = 0o556 let next = 0o557 let open_ = 0o560 let options = 0o561 let previous = 0o562 let redo = 0o563 let reference = 0o564 let refresh = 0o565 let replace = 0o566 let restart = 0o567 let resume = 0o570 let save = 0o571 let sbeg = 0o572 let scancel = 0o573 let scommand = 0o574 let scopy = 0o575 let screate = 0o576 let sdc = 0o577 let sdl = 0o600 let select = 0o601 let send = 0o602 let seol = 0o603 let sexit = 0o604 let sfind = 0o605 let shelp = 0o606 let shome = 0o607 let sic = 0o610 let sleft = 0o611 let smessage = 0o612 let smove = 0o613 let snext = 0o614 let soptions = 0o615 let sprevious = 0o616 let sprint = 0o617 let sredo = 0o620 let sreplace = 0o621 let sright = 0o622 let srsume = 0o623 let ssave = 0o624 let ssuspend = 0o625 let sundo = 0o626 let suspend = 0o627 let undo = 0o630 let mouse = 0o631 let resize = 0o632 let max = 0o777 let f n = f0 + n end wyrd-1.4.4/curses/README0000644000175000017500000000046310757447266013402 0ustar paulpaulThese curses bindings for OCaml are derived from the Objective Caml Text Mode Kit (ocaml-tmk). This code is released under the GNU LGPL; for details, see 'COPYING'. The ocaml-tmk project may be found at http://www.nongnu.org/ocaml-tmk/ . # arch-tag: DO_NOT_CHANGE_462d13eb-d2c3-405a-8dca-8204539772d0 wyrd-1.4.4/curses/curses.ml.in0000644000175000017500000001111510757447266014761 0ustar paulpaultype window type screen type terminal type chtype = int type attr_t = int type err = bool #define quote(a) #a #define ML0(f,tr) \ external f : unit -> tr = quote(mlcurses_##f) #define ML1(f,tr,ta) \ external f : ta -> tr = quote(mlcurses_##f) #define ML2(f,tr,ta,tb) \ external f : ta -> tb -> tr = quote(mlcurses_##f) #define ML3(f,tr,ta,tb,tc) \ external f : ta -> tb -> tc -> tr = quote(mlcurses_##f) #define ML4(f,tr,ta,tb,tc,td) \ external f : ta -> tb -> tc -> td -> tr = quote(mlcurses_##f) #define ML5(f,tr,ta,tb,tc,td,te) \ external f : ta -> tb -> tc -> td -> te -> tr = quote(mlcurses_##f) #define ML6(f,tr,ta,tb,tc,td,te,tf) \ external f : ta -> tb -> tc -> td -> te -> tf -> tr \ = quote(mlcurses_##f##_bytecode) quote(mlcurses_##f##_native) #define ML7(f,tr,ta,tb,tc,td,te,tf,tg) \ external f : ta -> tb -> tc -> td -> te -> tf -> tg -> tr \ = quote(mlcurses_##f##_bytecode) quote(mlcurses_##f##_native) #define ML8(f,tr,ta,tb,tc,td,te,tf,tg,th) \ external f : ta -> tb -> tc -> td -> te -> tf -> tg -> th -> tr \ = quote(mlcurses_##f##_bytecode) quote(mlcurses_##f##_native) #define ML9(f,tr,ta,tb,tc,td,te,tf,tg,th,ti) \ external f : ta -> tb -> tc -> td -> te -> tf -> tg -> th -> ti -> tr \ = quote(mlcurses_##f##_bytecode) quote(mlcurses_##f##_native) #define ML0d(f,tr) ML0(f,tr) #define ML1d(f,tr,ta) ML1(f,tr,ta) #define ML2d(f,tr,ta,tb) ML2(f,tr,ta,tb) #define ML3d(f,tr,ta,tb,tc) ML3(f,tr,ta,tb,tc) #define ML4d(f,tr,ta,tb,tc,td) ML4(f,tr,ta,tb,tc,td) #define ML5d(f,tr,ta,tb,tc,td,te) ML5(f,tr,ta,tb,tc,td,te) #define ML6d(f,tr,ta,tb,tc,td,te,tf) ML6(f,tr,ta,tb,tc,td,te,tf) #define BEG (* #define BEG0 BEG #define BEG1 BEG #define BEG2 BEG #define BEG3 BEG #define BEG4 BEG #define BEG5 BEG #define BEG6 BEG #define BEG7 BEG #define BEG8 BEG #define BEG9 BEG #define END *) module Acs = struct type acs = { ulcorner: chtype; llcorner: chtype; urcorner: chtype; lrcorner: chtype; ltee: chtype; rtee: chtype; btee: chtype; ttee: chtype; hline: chtype; vline: chtype; plus: chtype; s1: chtype; s9: chtype; diamond: chtype; ckboard: chtype; degree: chtype; plminus: chtype; bullet: chtype; larrow: chtype; rarrow: chtype; darrow: chtype; uarrow: chtype; board: chtype; lantern: chtype; block: chtype; s3: chtype; s7: chtype; lequal: chtype; gequal: chtype; pi: chtype; nequal: chtype; sterling: chtype } let bssb a = a.ulcorner let ssbb a = a.llcorner let bbss a = a.urcorner let sbbs a = a.lrcorner let sbss a = a.rtee let sssb a = a.ltee let ssbs a = a.btee let bsss a = a.ttee let bsbs a = a.hline let sbsb a = a.vline let ssss a = a.plus end #include "functions.c" (* these two were written separately in ml_curses.c, * to permit proper threading behavior *) ML0(getch,int) ML1(wgetch,int,window) let null_window = null_window () let bool_terminfo_variables = Hashtbl.create 67 let num_terminfo_variables = Hashtbl.create 67 let str_terminfo_variables = Hashtbl.create 601 let () = let rec ins f h n = let (a, b, c) = f n in if a = "" then () else ( Hashtbl.add h c (a, b); ins f h (n + 1) ) in ins bool_terminfo_variable bool_terminfo_variables 0; ins num_terminfo_variable num_terminfo_variables 0; ins str_terminfo_variable str_terminfo_variables 0 /* (* Bon, je vais recopier les constantes directement, parceque je n'ai * aucune idée de comment générer ça automatiquement proprement. Si ça ne * marche pas chez vous, il vous suffit de regarder l'include, et de * corriger à la main. Faites-le moi savoir, à tout hasard... *) */ module A = struct let normal = 0 let attributes = 0x7FFFFF00 let chartext = 0x000000FF let color = 0x0000FF00 let standout = 0x00010000 let underline = 0x00020000 let reverse = 0x00040000 let blink = 0x00080000 let dim = 0x00100000 let bold = 0x00200000 let altcharset = 0x00400000 let invis = 0x00800000 let protect = 0x01000000 let horizontal = 0x02000000 let left = 0x04000000 let low = 0x08000000 let right = 0x10000000 let top = 0x20000000 let vertical = 0x40000000 let combine = List.fold_left (lor) 0 let color_pair n = (n lsl 8) land color let pair_number a = (a land color) lsr 8 end (*/* Je sais, c'est moche, mais ça marche */*) module WA = A module Color = struct let black = 0 let red = 1 let green = 2 let yellow = 3 let blue = 4 let magenta = 5 let cyan = 6 let white = 7 end module Key = struct #include "keys.ml" let f n = f0 + n end wyrd-1.4.4/configure0000755000175000017500000037061110757447267013133 0ustar paulpaul#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="install.ml.in" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias OCAMLC OCAMLOPT OCAMLCDOTOPT OCAMLOPTDOTOPT OCAMLDEP OCAMLLEX OCAMLLEXDOTOPT OCAMLYACC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT REMINDPATH OCAMLBEST OCAMLVERSION OCAMLLIB OCAMLWIN32 EXE CURSES_HEADER CURSES_TERM_H CURSES_LIB BOOL_WIDE_CURSES LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-utf8 enable UTF-8 output (requires ncurses wide char support) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # optional arguments # Check whether --enable-utf8 was given. if test "${enable_utf8+set}" = set; then enableval=$enable_utf8; try_utf8=$enable_utf8 else try_utf8=no fi # Check for Ocaml compilers # we first look for ocamlc in the path; if not present, we fail # Extract the first word of "ocamlc", so it can be a program name with args. set dummy ocamlc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLC"; then ac_cv_prog_OCAMLC="$OCAMLC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLC="ocamlc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLC" && ac_cv_prog_OCAMLC="no" fi fi OCAMLC=$ac_cv_prog_OCAMLC if test -n "$OCAMLC"; then { echo "$as_me:$LINENO: result: $OCAMLC" >&5 echo "${ECHO_T}$OCAMLC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLC" = no ; then { { echo "$as_me:$LINENO: error: Cannot find ocamlc." >&5 echo "$as_me: error: Cannot find ocamlc." >&2;} { (exit 1); exit 1; }; } fi # we extract Ocaml version number and library path OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` echo "ocaml version is $OCAMLVERSION" OCAMLLIB=`$OCAMLC -v | tail -n 1 | cut -f 4 -d " "` echo "ocaml library path is $OCAMLLIB" # check for sufficient OCAMLVERSION OCAMLMAJORVERSION=`echo $OCAMLVERSION | cut -d '.' -f 1` OCAMLMINORVERSION=`echo $OCAMLVERSION | cut -d '.' -f 2` if test $OCAMLMAJORVERSION -lt 3 ; then { { echo "$as_me:$LINENO: error: Wyrd requires OCaml version 3.08 or greater." >&5 echo "$as_me: error: Wyrd requires OCaml version 3.08 or greater." >&2;} { (exit 1); exit 1; }; } else if test $OCAMLMINORVERSION -lt 8 ; then { { echo "$as_me:$LINENO: error: Wyrd requires OCaml version 3.08 or greater." >&5 echo "$as_me: error: Wyrd requires OCaml version 3.08 or greater." >&2;} { (exit 1); exit 1; }; } fi fi # then we look for ocamlopt; if not present, we issue a warning # if the version is not the same, we also discard it # we set OCAMLBEST to "opt" or "byte", whether ocamlopt is available or not # Extract the first word of "ocamlopt", so it can be a program name with args. set dummy ocamlopt; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLOPT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLOPT"; then ac_cv_prog_OCAMLOPT="$OCAMLOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLOPT="ocamlopt" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLOPT" && ac_cv_prog_OCAMLOPT="no" fi fi OCAMLOPT=$ac_cv_prog_OCAMLOPT if test -n "$OCAMLOPT"; then { echo "$as_me:$LINENO: result: $OCAMLOPT" >&5 echo "${ECHO_T}$OCAMLOPT" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi OCAMLBEST=byte if test "$OCAMLOPT" = no ; then { echo "$as_me:$LINENO: WARNING: Cannot find ocamlopt; bytecode compilation only." >&5 echo "$as_me: WARNING: Cannot find ocamlopt; bytecode compilation only." >&2;} else { echo "$as_me:$LINENO: checking ocamlopt version" >&5 echo $ECHO_N "checking ocamlopt version... $ECHO_C" >&6; } TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { echo "$as_me:$LINENO: result: differs from ocamlc; ocamlopt discarded." >&5 echo "${ECHO_T}differs from ocamlc; ocamlopt discarded." >&6; } OCAMLOPT=no else { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; } OCAMLBEST=opt fi fi # checking for ocamlc.opt # Extract the first word of "ocamlc.opt", so it can be a program name with args. set dummy ocamlc.opt; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLCDOTOPT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLCDOTOPT"; then ac_cv_prog_OCAMLCDOTOPT="$OCAMLCDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLCDOTOPT="ocamlc.opt" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLCDOTOPT" && ac_cv_prog_OCAMLCDOTOPT="no" fi fi OCAMLCDOTOPT=$ac_cv_prog_OCAMLCDOTOPT if test -n "$OCAMLCDOTOPT"; then { echo "$as_me:$LINENO: result: $OCAMLCDOTOPT" >&5 echo "${ECHO_T}$OCAMLCDOTOPT" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLCDOTOPT" != no ; then { echo "$as_me:$LINENO: checking ocamlc.opt version" >&5 echo $ECHO_N "checking ocamlc.opt version... $ECHO_C" >&6; } TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { echo "$as_me:$LINENO: result: differs from ocamlc; ocamlc.opt discarded." >&5 echo "${ECHO_T}differs from ocamlc; ocamlc.opt discarded." >&6; } else { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; } OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != no ; then # Extract the first word of "ocamlopt.opt", so it can be a program name with args. set dummy ocamlopt.opt; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLOPTDOTOPT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLOPTDOTOPT"; then ac_cv_prog_OCAMLOPTDOTOPT="$OCAMLOPTDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLOPTDOTOPT="ocamlopt.opt" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLOPTDOTOPT" && ac_cv_prog_OCAMLOPTDOTOPT="no" fi fi OCAMLOPTDOTOPT=$ac_cv_prog_OCAMLOPTDOTOPT if test -n "$OCAMLOPTDOTOPT"; then { echo "$as_me:$LINENO: result: $OCAMLOPTDOTOPT" >&5 echo "${ECHO_T}$OCAMLOPTDOTOPT" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLOPTDOTOPT" != no ; then { echo "$as_me:$LINENO: checking ocamlc.opt version" >&5 echo $ECHO_N "checking ocamlc.opt version... $ECHO_C" >&6; } TMPVER=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVER" != "$OCAMLVERSION" ; then { echo "$as_me:$LINENO: result: differs from ocamlc; ocamlopt.opt discarded." >&5 echo "${ECHO_T}differs from ocamlc; ocamlopt.opt discarded." >&6; } else { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; } OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi # ocamldep should also be present in the path # Extract the first word of "ocamldep", so it can be a program name with args. set dummy ocamldep; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLDEP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLDEP"; then ac_cv_prog_OCAMLDEP="$OCAMLDEP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLDEP="ocamldep" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLDEP" && ac_cv_prog_OCAMLDEP="no" fi fi OCAMLDEP=$ac_cv_prog_OCAMLDEP if test -n "$OCAMLDEP"; then { echo "$as_me:$LINENO: result: $OCAMLDEP" >&5 echo "${ECHO_T}$OCAMLDEP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLDEP" = no ; then { { echo "$as_me:$LINENO: error: Cannot find ocamldep." >&5 echo "$as_me: error: Cannot find ocamldep." >&2;} { (exit 1); exit 1; }; } fi # Extract the first word of "ocamllex", so it can be a program name with args. set dummy ocamllex; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLLEX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLLEX"; then ac_cv_prog_OCAMLLEX="$OCAMLLEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLLEX="ocamllex" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLLEX" && ac_cv_prog_OCAMLLEX="no" fi fi OCAMLLEX=$ac_cv_prog_OCAMLLEX if test -n "$OCAMLLEX"; then { echo "$as_me:$LINENO: result: $OCAMLLEX" >&5 echo "${ECHO_T}$OCAMLLEX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLLEX" = no ; then { { echo "$as_me:$LINENO: error: Cannot find ocamllex." >&5 echo "$as_me: error: Cannot find ocamllex." >&2;} { (exit 1); exit 1; }; } else # Extract the first word of "ocamllex.opt", so it can be a program name with args. set dummy ocamllex.opt; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLLEXDOTOPT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLLEXDOTOPT"; then ac_cv_prog_OCAMLLEXDOTOPT="$OCAMLLEXDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLLEXDOTOPT="ocamllex.opt" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLLEXDOTOPT" && ac_cv_prog_OCAMLLEXDOTOPT="no" fi fi OCAMLLEXDOTOPT=$ac_cv_prog_OCAMLLEXDOTOPT if test -n "$OCAMLLEXDOTOPT"; then { echo "$as_me:$LINENO: result: $OCAMLLEXDOTOPT" >&5 echo "${ECHO_T}$OCAMLLEXDOTOPT" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLLEXDOTOPT" != no ; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi # Extract the first word of "ocamlyacc", so it can be a program name with args. set dummy ocamlyacc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OCAMLYACC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OCAMLYACC"; then ac_cv_prog_OCAMLYACC="$OCAMLYACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OCAMLYACC="ocamlyacc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLYACC" && ac_cv_prog_OCAMLYACC="no" fi fi OCAMLYACC=$ac_cv_prog_OCAMLYACC if test -n "$OCAMLYACC"; then { echo "$as_me:$LINENO: result: $OCAMLYACC" >&5 echo "${ECHO_T}$OCAMLYACC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$OCAMLYACC" = no ; then { { echo "$as_me:$LINENO: error: Cannot find ocamlyacc." >&5 echo "$as_me: error: Cannot find ocamlyacc." >&2;} { (exit 1); exit 1; }; } fi # platform { echo "$as_me:$LINENO: checking platform" >&5 echo $ECHO_N "checking platform... $ECHO_C" >&6; } if echo "let _ = Sys.os_type" | ocaml | grep -q Win32; then { echo "$as_me:$LINENO: result: Win32" >&5 echo "${ECHO_T}Win32" >&6; } OCAMLWIN32=yes EXE=.exe else { echo "$as_me:$LINENO: result: not Win32" >&5 echo "${ECHO_T}not Win32" >&6; } OCAMLWIN32=no EXE= fi # find a C compiler ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ORIG_LIBS="$LIBS" ORIG_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CURSES_INCLUDE $ORIG_CPPFLAGS" # check for ncurses { echo "$as_me:$LINENO: checking for working ncurses library" >&5 echo $ECHO_N "checking for working ncurses library... $ECHO_C" >&6; } if test "$try_utf8" != "no" then LIBS="-lncursesw $ORIG_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { initscr(); use_default_colors() ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then CURSES_LIB=-lncursesw cat >>confdefs.h <<\_ACEOF #define CURSES_HEADER _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi if test -z "$CURSES_LIB" then LIBS="-lncurses $ORIG_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { initscr(); use_default_colors() ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then CURSES_LIB=-lncurses cat >>confdefs.h <<\_ACEOF #define CURSES_HEADER _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="-lncurses $ORIG_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { initscr(); use_default_colors() ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then CURSES_LIB=-lncurses cat >>confdefs.h <<\_ACEOF #define CURSES_HEADER _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="-lcurses $ORIG_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { initscr(); use_default_colors() ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then CURSES_LIB=-lcurses cat >>confdefs.h <<\_ACEOF #define CURSES_HEADER _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="-lncurses $ORIG_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { initscr(); use_default_colors() ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then CURSES_LIB=-lcurses cat >>confdefs.h <<\_ACEOF #define CURSES_HEADER _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi if test -n "$CURSES_LIB" then { echo "$as_me:$LINENO: result: found in $CURSES_LIB" >&5 echo "${ECHO_T}found in $CURSES_LIB" >&6; } else { { echo "$as_me:$LINENO: error: not found" >&5 echo "$as_me: error: not found" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for ncurses term.h" >&5 echo $ECHO_N "checking for ncurses term.h... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { TERMTYPE __dummy ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then TERM_H_STRING="" cat >>confdefs.h <<\_ACEOF #define CURSES_TERM_H _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { TERMTYPE __dummy ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then TERM_H_STRING="" cat >>confdefs.h <<\_ACEOF #define CURSES_TERM_H _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { TERMTYPE __dummy ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then TERM_H_STRING="" cat >>confdefs.h <<\_ACEOF #define CURSES_TERM_H _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test -n "$TERM_H_STRING" then { echo "$as_me:$LINENO: result: found in $TERM_H_STRING" >&5 echo "${ECHO_T}found in $TERM_H_STRING" >&6; } else { { echo "$as_me:$LINENO: error: not found" >&5 echo "$as_me: error: not found" >&2;} { (exit 1); exit 1; }; } fi # check whether the detected ncurses has wide char support BOOL_WIDE_CURSES="false" if test -n "$CURSES_LIB" then LIBS="$CURSES_LIB $ORIG_LIBS" if test "$try_utf8" != "no" then { echo "$as_me:$LINENO: checking for wide character support in ncurses library" >&5 echo $ECHO_N "checking for wide character support in ncurses library... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include CURSES_HEADER int main () { wchar_t wch = 0; addnwstr(&wch, 1); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } cat >>confdefs.h <<\_ACEOF #define HAVE_WIDE_CURSES 1 _ACEOF BOOL_WIDE_CURSES="true" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi fi CPPFLAGS="$ORIG_CPPFLAGS" LIBS="$ORIG_LIBS" # check Remind version # Extract the first word of "remind", so it can be a program name with args. set dummy remind; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_REMINDPATH+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $REMINDPATH in [\\/]* | ?:[\\/]*) ac_cv_path_REMINDPATH="$REMINDPATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_REMINDPATH="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_REMINDPATH" && ac_cv_path_REMINDPATH="not found" ;; esac fi REMINDPATH=$ac_cv_path_REMINDPATH if test -n "$REMINDPATH"; then { echo "$as_me:$LINENO: result: $REMINDPATH" >&5 echo "${ECHO_T}$REMINDPATH" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test x"$REMINDPATH" != x"not found"; then { echo "$as_me:$LINENO: checking remind version" >&5 echo $ECHO_N "checking remind version... $ECHO_C" >&6; } REMINDVERSION=`strings $REMINDPATH | grep 03\.0` { echo "$as_me:$LINENO: result: $REMINDVERSION" >&5 echo "${ECHO_T}$REMINDVERSION" >&6; } REMMAJORVERSION=`echo $REMINDVERSION | cut -d '.' -f 1` REMMINORVERSION=`echo $REMINDVERSION | cut -d '.' -f 2` REMFIXVERSION=`echo $REMINDVERSION | cut -d '.' -f 3` if test $REMMAJORVERSION -lt 3 ; then { echo "$as_me:$LINENO: WARNING: Wyrd requires Remind version 03.01.00 or greater." >&5 echo "$as_me: WARNING: Wyrd requires Remind version 03.01.00 or greater." >&2;} else if test $REMMINORVERSION -lt 1 ; then { echo "$as_me:$LINENO: WARNING: Wyrd requires Remind version 03.01.00 or greater." >&5 echo "$as_me: WARNING: Wyrd requires Remind version 03.01.00 or greater." >&2;} fi fi else { echo "$as_me:$LINENO: WARNING: Wyrd requires Remind version 03.00.24 or greater." >&5 echo "$as_me: WARNING: Wyrd requires Remind version 03.00.24 or greater." >&2;} fi # substitutions to perform # Finally create the Makefile from Makefile.in ac_config_files="$ac_config_files Makefile install.ml" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "install.ml") CONFIG_FILES="$CONFIG_FILES install.ml" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim OCAMLC!$OCAMLC$ac_delim OCAMLOPT!$OCAMLOPT$ac_delim OCAMLCDOTOPT!$OCAMLCDOTOPT$ac_delim OCAMLOPTDOTOPT!$OCAMLOPTDOTOPT$ac_delim OCAMLDEP!$OCAMLDEP$ac_delim OCAMLLEX!$OCAMLLEX$ac_delim OCAMLLEXDOTOPT!$OCAMLLEXDOTOPT$ac_delim OCAMLYACC!$OCAMLYACC$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim REMINDPATH!$REMINDPATH$ac_delim OCAMLBEST!$OCAMLBEST$ac_delim OCAMLVERSION!$OCAMLVERSION$ac_delim OCAMLLIB!$OCAMLLIB$ac_delim OCAMLWIN32!$OCAMLWIN32$ac_delim EXE!$EXE$ac_delim CURSES_HEADER!$CURSES_HEADER$ac_delim CURSES_TERM_H!$CURSES_TERM_H$ac_delim CURSES_LIB!$CURSES_LIB$ac_delim BOOL_WIDE_CURSES!$BOOL_WIDE_CURSES$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 64; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi chmod a-w Makefile # arch-tag: DO_NOT_CHANGE_3852958f-9da5-4ee1-8a22-ac63ac00aaac wyrd-1.4.4/utility.ml0000644000175000017500000002743410757447265013261 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* utility.ml * * miscellaneous helper functions that don't really fit elsewhere *) exception String_of_tm_mon_failure of string exception String_of_tm_wday_failure of string exception Unicode_length_failure of string (* append a file to a directory, with the proper number * of slashes *) let join_path dirname filename = let dir_last = dirname.[String.length dirname - 1] and file_first = filename.[0] in if dir_last = '/' && file_first = '/' then dirname ^ (Str.string_after filename 1) else if dir_last <> '/' && file_first <> '/' then dirname ^ "/" ^ filename else dirname ^ filename (* Perform shell expansion of environment variables. *) let shell_expand text = let split_regex = Str.regexp "=" in (* Get a list of all environment variable mappings *) let add_mapping env_mapping mapping_list = match Str.split split_regex env_mapping with | key :: value :: [] -> (key, value) :: mapping_list | _ -> mapping_list in let env_mappings = Array.fold_right add_mapping (Unix.environment ()) [] in let rec apply_mappings mapping_list s = match mapping_list with | [] -> s | (var, expansion) :: tail -> let var_regex = Str.regexp_string ("$" ^ var) in apply_mappings tail (Str.global_replace var_regex expansion s) in apply_mappings env_mappings text (* If the filename starts with "~", substitute $HOME. Then do shell * expansion on the resulting string. *) let expand_file filename = let tilde_expansion = if String.length filename >= 2 && Str.string_before filename 2 = "~/" then "$HOME" ^ Str.string_after filename 1 else filename in shell_expand tilde_expansion (* Do whatever is necessary to open up a file for writing. If it already exists, * open it as-is. If it does not exist, make sure that all prefix directories * do exist, then open a new file. *) let open_or_create_out_gen is_binary filename = let exp_file = expand_file filename in (* Test whether the file exists *) if Sys.file_exists exp_file then if is_binary then open_out_bin exp_file else open_out exp_file else (* Check whether all directories exist *) let dir_path = Filename.dirname exp_file in let dir_list = Str.split (Str.regexp "/+") dir_path in (* if necessary, add the first "/" to the first directory *) let slash_dir_list = if not (Filename.is_relative dir_path) then ("/" ^ (List.hd dir_list)) :: (List.tl dir_list) else dir_list in let rec make_directories d_list = match d_list with | [] -> () | d :: tail -> begin try Sys.chdir d with Sys_error err_msg -> begin let _ = Sys.command ("mkdir " ^ d) in Sys.chdir d end end; make_directories tail in make_directories slash_dir_list; if is_binary then open_out_bin (Filename.basename exp_file) else open_out (Filename.basename exp_file) let open_or_create_out_bin filename = open_or_create_out_gen true filename let open_or_create_out_ascii filename = open_or_create_out_gen false filename (* open a filename, with tilde/$HOME expansion *) let expand_open_in_gen is_binary filename = (* If the filename starts with "~", substitute $HOME *) if is_binary then open_in_bin (expand_file filename) else open_in (expand_file filename) let expand_open_in_bin filename = expand_open_in_gen true filename let expand_open_in_ascii filename = expand_open_in_gen false filename let string_of_tm_mon i = match i with | 0 -> "Jan" | 1 -> "Feb" | 2 -> "Mar" | 3 -> "Apr" | 4 -> "May" | 5 -> "Jun" | 6 -> "Jul" | 7 -> "Aug" | 8 -> "Sep" | 9 -> "Oct" |10 -> "Nov" |11 -> "Dec" | x -> raise (String_of_tm_mon_failure ("unknown month " ^ (string_of_int x))) let full_string_of_tm_mon i = match i with | 0 -> "January" | 1 -> "February" | 2 -> "March" | 3 -> "April" | 4 -> "May" | 5 -> "June" | 6 -> "July" | 7 -> "August" | 8 -> "September" | 9 -> "October" |10 -> "November" |11 -> "December" | x -> raise (String_of_tm_mon_failure ("unknown month " ^ (string_of_int x))) let short_string_of_tm_wday i = match i with | 0 -> "Su" | 1 -> "Mo" | 2 -> "Tu" | 3 -> "We" | 4 -> "Th" | 5 -> "Fr" | 6 -> "Sa" | x -> raise (String_of_tm_wday_failure ("unknown weekday " ^ (string_of_int x))) let string_of_tm_wday i = match i with | 0 -> "Sun" | 1 -> "Mon" | 2 -> "Tue" | 3 -> "Wed" | 4 -> "Thu" | 5 -> "Fri" | 6 -> "Sat" | x -> raise (String_of_tm_wday_failure ("unknown weekday " ^ (string_of_int x))) let full_string_of_tm_wday i = match i with | 0 -> "Sunday" | 1 -> "Monday" | 2 -> "Tuesday" | 3 -> "Wednesday" | 4 -> "Thursday" | 5 -> "Friday" | 6 -> "Saturday" | x -> raise (String_of_tm_wday_failure ("unknown weekday " ^ (string_of_int x))) (* it's useful to have an empty date record to save some typing *) let empty_tm = { Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0; Unix.tm_mday = 1; Unix.tm_mon = 0; Unix.tm_year = 1900; Unix.tm_wday = 0; Unix.tm_yday = 0; Unix.tm_isdst = false } (* strip whitespace *) let lstrip s = (* Any amount of whitespace, followed by a non-whitespace char, * followed by any number of characters. If match fails, * then the string must be entirely whitespace. *) let re = Str.regexp "[ \t]*\\([^ \t].*\\)" in if Str.string_match re s 0 then Str.replace_first re "\\1" s else "" let rstrip s = (* Any number of characters, followed by a non-whitespace char, * followed by any number of whitespace chars. If match * fails, then the string must be entirely whitespace. *) let re = Str.regexp "\\(.*[^ \t]\\).*" in if Str.string_match re s 0 then Str.replace_first re "\\1" s else "" let strip s = lstrip (rstrip s) (* Use the shell to open a process, read all output from both stdout and stderr, * and close the pipes to the process again. Returns a list of lines from * stdout, and a list of lines from stderr. * * Uses select(), so it should be robust to I/O buffering synchronization * issues. *) let read_all_shell_command_output shell_command = let (in_read, in_write) = Unix.pipe () and (out_read, out_write) = Unix.pipe () and (err_read, err_write) = Unix.pipe () in let rec read_output out_str err_str out_done err_done = if out_done && err_done then (out_str, err_str) else begin let out_lst = if out_done then [] else [out_read] and err_lst = if err_done then [] else [err_read] in (* find some output to read *) let (read_list, _, _) = Unix.select (out_lst @ err_lst) [] [] (10.0) in if List.length read_list > 0 then begin let chan = List.hd read_list in let buf = String.make 256 ' ' in let chars_read = Unix.read chan buf 0 256 in if chars_read = 0 then (* no chars read indicates EOF *) if chan = out_read then read_output out_str err_str true err_done else read_output out_str err_str out_done true else (* if 1-256 characters are read, append them to the proper * buffer and continue *) let s = String.sub buf 0 chars_read in if chan = out_read then read_output (out_str ^ s) err_str out_done err_done else read_output out_str (err_str ^ s) out_done err_done end else (out_str, err_str) end in (* launch the shell process *) let pid = Unix.create_process "/bin/sh" [| "/bin/sh"; "-c"; shell_command |] in_read out_write err_write in (* these belong to remind, so close them off *) Unix.close in_read; Unix.close out_write; Unix.close err_write; let (out_str, err_str) = read_output "" "" false false in (* clean up remind zombie *) let _ = Unix.waitpid [] pid in (* close off our end of the IPC pipes *) Unix.close in_write; Unix.close out_read; Unix.close err_read; let newline_regex = Str.regexp "\n" in let out_lines = Str.split newline_regex out_str and err_lines = Str.split newline_regex err_str in (out_lines, err_lines) (* Compute the number of bytes required to store a utf-8 character. * Input is the first byte of the character. *) let utf8_width (byte : char) = let c = Char.code byte in if c < 0x80 then 1 else if c < 0xc0 then raise (Unicode_length_failure "illegal byte") else if c < 0xe0 then 2 else if c < 0xf0 then 3 else if c < 0xf8 then 4 else if c < 0xfc then 5 else if c < 0xfe then 6 else raise (Unicode_length_failure "illegal byte") (* Compute the number of UTF-8 characters contained in an ocaml String. *) let utf8_len s = let s_len = String.length s in let rec len_aux byte_pos char_count = if byte_pos >= s_len then char_count else let num_bytes = utf8_width s.[byte_pos] in len_aux (byte_pos + num_bytes) (succ char_count) in if Install.wide_ncurses then len_aux 0 0 else (* If build process does not detect ncursesw, then fall back * on standard string behavior. *) s_len (* Form the substring of all characters from 's' in positions before 'n', * where 'n' may be measured in characters rather than bytes. Does the right * thing for utf-8 wide characters. *) let utf8_string_before s n = let rec build_substr substr utf8_pos byte_pos = if utf8_pos >= n then substr else let num_new_bytes = utf8_width s.[byte_pos] in let new_bytes = String.make num_new_bytes s.[byte_pos] in for i = 1 to pred num_new_bytes do new_bytes.[i] <- s.[byte_pos + i] done; build_substr (substr ^ new_bytes) (succ utf8_pos) (byte_pos + num_new_bytes) in if Install.wide_ncurses then build_substr "" 0 0 else (* If we're not using utf-8, fall back on standard string behavior. *) Str.string_before s n (* Form the substring of all characters from 's' in positions 'n' or greater, * where 'n' may be measured in characters rather than bytes. Does the right * thing for utf-8 wide characters. *) let utf8_string_after s n = if Install.wide_ncurses then begin let starting_byte = ref 0 in for utf8_char = 0 to pred n do starting_byte := !starting_byte + (utf8_width s.[!starting_byte]) done; Str.string_after s !starting_byte end else (* If we're not using utf-8, fall back on standard string behavior. *) Str.string_after s n (* arch-tag: DO_NOT_CHANGE_a87790db-2dd0-496c-9620-ed968f3253fd *) wyrd-1.4.4/locale_wrap.c0000644000175000017500000000243110757447265013646 0ustar paulpaul/* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . */ /* OCaml binding for setlocale(), which is required to kick ncurses * into rendering non-ASCII chars. */ #include #include #include #include #include value ml_setlocale(value category, value setting) { CAMLparam2(category, setting); CAMLlocal1(result); result = caml_copy_string(setlocale(Int_val(category), String_val(setting))); CAMLreturn(result); } wyrd-1.4.4/wyrd.spec0000644000175000017500000000236710757447265013063 0ustar paulpaul############ wyrd.spec ############ # This is for debug-flavor. Do not remove. Package is stripped conditionally. #%#define __os_install_post %{nil} # %#define __spec_install_post /usr/lib/rpm/brp-compress %define name wyrd %define version 1.4.1 %define sfx tar.gz %define release 1 %define descr term based calendar frontend for remind Summary: %{descr} Name: %{name} Version: %{version} Release: %{release} Source0: %{name}-%{version}.%{sfx} Copyright: GPL Group: System Environment/Libs BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot #Prefix: %#{_prefix} #URL: %description %{descr} %prep case "${RPM_COMMAND:-all}" in all) %setup -q ;; esac %build case "${RPM_COMMAND:-all}" in all|config) #export CFLAGS="$RPM_OPT_FLAGS -O1 -g" #./configure --prefix=%{prefix} %configure ;; esac case "${RPM_COMMAND:-all}" in all|config|build) make ;; esac %install case "${RPM_COMMAND:-all}" in all|config|build|install) mkdir -p $RPM_BUILD_ROOT/etc make DESTDIR=$RPM_BUILD_ROOT install ;;esac %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc COPYING README TODO %{_prefix}/* /etc/* %changelog * Fri Dec 26 2003 Richard Zidlicky - created skel.spec # arch-tag: DO_NOT_CHANGE_0dfb61c0-79d1-4f5a-a711-b24213b5dc62 wyrd-1.4.4/Makefile.in0000644000175000017500000001453410757447264013265 0ustar paulpaul# # sample Makefile for Objective Caml # Copyright (C) 2001 Jean-Christophe FILLIATRE # # modified 10/26/2003 by Paul Pelzl, for the purpose of building Orpie # modified 03/28/2005 by Paul Pelzl, for the purpose of building Wyrd # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License version 2, as published by the Free Software Foundation. # # This library 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 Library General Public License version 2 for more details # (enclosed in the file LGPL). # where to install the binaries, rcfiles, manpages, etc. prefix = @prefix@ exec_prefix = @exec_prefix@ sysconfdir = @sysconfdir@ datarootdir = @datarootdir@ BINDIR = $(DESTDIR)/@bindir@ MANDIR = $(DESTDIR)/@mandir@ # other variables set by ./configure OCAMLC = @OCAMLC@ OCAMLOPT = @OCAMLOPT@ OCAMLDEP = @OCAMLDEP@ OCAMLLIB = @OCAMLLIB@ OCAMLBEST = @OCAMLBEST@ OCAMLLEX = @OCAMLLEX@ OCAMLYACC = @OCAMLYACC@ OCAMLVERSION = @OCAMLVERSION@ OCAMLWIN32 = @OCAMLWIN32@ EXE = @EXE@ DEFS = @DEFS@ CC = @CC@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ CURSES_LIB = @CURSES_LIB@ INCLUDES = -I ./curses BFLAGS = -pp camlp4o -g $(INCLUDES) OFLAGS = -pp camlp4o $(INCLUDES) BLFLAGS = -custom -cclib '$(LDFLAGS) $(CURSES_LIB) -lm' OLFLAGS = -cclib '$(LDFLAGS) $(CURSES_LIB) -lm' DEPFLAGS = -pp camlp4o # main target ############# NAME = wyrd all: $(OCAMLBEST) # bytecode and native-code compilation ###################################### CMO = install.cmo version.cmo utility.cmo rcfile.cmo time_lang.cmo interface.cmo cal.cmo \ remind.cmo interface_draw.cmo interface_main.cmo locale.cmo main.cmo CMX = $(CMO:.cmo=.cmx) CMA = str.cma unix.cma CMXA = $(CMA:.cma=.cmxa) COBJS = locale_wrap.o CURSES_CMO = curses/curses.cmo CURSES_CMX = curses/curses.cmx CURSES_COBJS = curses/ml_curses.o CURSES_BOBJS = $(CURSES_CMO) $(CURSES_COBJS) CURSES_OOBJS = $(CURSES_CMX) $(CURSES_COBJS) GENERATED = version.ml byte: $(NAME).byte opt: $(NAME).opt static: $(NAME).static-opt $(NAME).byte: $(COBJS) $(CURSES_BOBJS) $(CMO) $(OCAMLC) $(BFLAGS) $(BLFLAGS) -o $@ $(CURSES_BOBJS) $(COBJS) $(CMA) $(CMO) $(NAME).opt: $(COBJS) $(CURSES_OOBJS) $(CMX) $(OCAMLOPT) $(OFLAGS) -o $@ $(CURSES_OOBJS) $(COBJS) $(CMXA) $(CMX) $(OLFLAGS) # static build seems to require mashing all the C objects into a library $(NAME).static-opt: $(COBJS) $(CMX) $(CURSES_OOBJS) my-static-libs $(OCAMLOPT) $(OFLAGS) -I . -ccopt -static -cclib '-lmycurses $(CURSES_LIB) -lm' -o $@ \ $(COBJS) $(CMXA) curses.cmx $(CMX) strip $(NAME).static-opt my-static-libs: ar cr libmycurses.a curses/*.o VERSION=1.4.4 version.ml: Makefile echo "let version = \""$(VERSION)"\"" > version.ml echo "let date = \""`date`"\"" >> version.ml # installation ############## install-indep: mkdir -p $(BINDIR) mkdir -p $(DESTDIR)/$(sysconfdir) mkdir -p $(MANDIR)/man1 mkdir -p $(MANDIR)/man5 install -m 644 wyrdrc $(DESTDIR)/$(sysconfdir) install -m 644 doc/wyrd.1 $(MANDIR)/man1/wyrd.1 install -m 644 doc/wyrdrc.5 $(MANDIR)/man5/wyrdrc.5 install: install-indep install -m 755 $(NAME).$(OCAMLBEST) $(BINDIR) mv $(BINDIR)/$(NAME).$(OCAMLBEST) $(BINDIR)/$(NAME) install-byte: install-indep install -m 755 $(NAME).byte $(BINDIR) mv $(BINDIR)/$(NAME).byte $(BINDIR)/$(NAME) install-opt: install-indep install -m 755 $(NAME).opt $(BINDIR) mv $(BINDIR)/$(NAME).opt $(BINDIR)/$(NAME) install-static: install-indep install -m 755 $(NAME).static-opt $(BINDIR) mv $(BINDIR)/$(NAME).static-opt $(BINDIR)/$(NAME) uninstall: rm -f $(BINDIR)/$(NAME)$(EXE) rm -f $(DESTDIR)/$(sysconfdir)/wyrdrc rm -f $(MANDIR)/man1/wyrd.1 rm -f $(MANDIR)/man5/wyrdrc.5 # generic rules ############### .SUFFIXES: # curses build rules curses-opt: $(CURSES_OOBJS) curses-byte: $(CURSES_BOBJS) curses/curses.ml: curses/curses.ml.in curses/functions.c $(MAKE) -C curses curses/functions.c: curses/functions.c.in $(MAKE) -C curses CURSES_INCLUDES = -I ./curses CURSES_BFLAGS = -g $(CURSES_INCLUDES) CURSES_OFLAGS = $(CURSES_INCLUDES) CURSES_CFLAGS = $(CPPFLAGS) $(DEFS) $(CFLAGS) -Wall -fPIC -DPIC curses/%.cmi : curses/%.mli $(OCAMLC) -c $(CURSES_BFLAGS) $< curses/%.cmo : curses/%.ml $(OCAMLC) -c $(CURSES_BFLAGS) $< curses/%.o : curses/%.ml $(OCAMLOPT) -c $(CURSES_OFLAGS) $< curses/%.cmx : curses/%.ml $(OCAMLOPT) -c $(CURSES_OFLAGS) $< curses/%.o : curses/%.c cd curses && $(OCAMLC) -ccopt "$(CURSES_CFLAGS)" -c $*.c # generic build rules for toplevel directory %.cmi : %.mli $(OCAMLC) -c $(BFLAGS) $< %.cmo : %.ml $(OCAMLC) -c $(BFLAGS) $< %.o : %.ml $(OCAMLOPT) -c $(OFLAGS) $< %.cmx : %.ml $(OCAMLOPT) -c $(OFLAGS) $< %.ml : %.mll $(OCAMLLEX) $< %.ml : %.mly $(OCAMLYACC) -v $< %.mli : %.mly $(OCAMLYACC) -v $< %.o : %.c $(OCAMLC) -c $< # Emacs tags ############ tags: find . -name "*.ml*" | sort -r | xargs \ etags "--regex=/let[ \t]+\([^ \t]+\)/\1/" \ "--regex=/let[ \t]+rec[ \t]+\([^ \t]+\)/\1/" \ "--regex=/and[ \t]+\([^ \t]+\)/\1/" \ "--regex=/type[ \t]+\([^ \t]+\)/\1/" \ "--regex=/exception[ \t]+\([^ \t]+\)/\1/" \ "--regex=/val[ \t]+\([^ \t]+\)/\1/" \ "--regex=/module[ \t]+\([^ \t]+\)/\1/" # vi tags ######### vtags: otags -vi -o tags *.ml # Makefile is rebuilt whenever Makefile.in or configure.in is modified ###################################################################### Makefile: Makefile.in config.status ./config.status config.status: configure ./config.status --recheck configure: configure.in autoconf # clean ####### partly-clean:: rm -f *.cm[iox] *.o *.a *~ rm -f $(GENERATED) rm -f $(NAME).byte $(NAME).opt $(NAME).static-opt rm -f *.aux *.log $(NAME).tex $(NAME).dvi $(NAME).ps curses-clean:: rm -f curses/*.cm[iox] curses/*.o *~ clean:: partly-clean curses-clean dist-clean distclean:: clean rm -f Makefile config.cache config.log config.status install.ml # depend ######## depend:: # $(MAKE) txtin_lexer.ml # $(MAKE) txtin_parser.ml $(OCAMLDEP) -pp camlp4o $(INCLUDES) *.ml *.mli > depend $(OCAMLDEP) -pp 'cpp -P -xassembler-with-cpp' -I ./curses curses/*.ml curses/*.mli >> depend include depend # arch-tag: DO_NOT_CHANGE_bdb62873-ffd0-4d79-819e-880467e18f28 wyrd-1.4.4/configure.in0000644000175000017500000002137110757447265013527 0ustar paulpaul# # autoconf input for Objective Caml programs # Copyright (C) 2001 Jean-Christophe Filliâtre # from a first script by Georges Mariano # # modified 10/26/03 by Paul Pelzl, for inclusion with Orpie # (added ocaml-gsl detection, removed unnecessary checks) # modified 03/28/05 by Paul Pelzl, for inclusion with Wyrd # (removed unnecessary gsl detection) # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License version 2, as published by the Free Software Foundation. # # This library 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 Library General Public License version 2 for more details # (enclosed in the file LGPL). # the script generated by autoconf from this input will set the following # variables: # OCAMLC "ocamlc" if present in the path, or a failure # or "ocamlc.opt" if present with same version number as ocamlc # OCAMLOPT "ocamlopt" (or "ocamlopt.opt" if present), or "no" # OCAMLBEST either "byte" if no native compiler was found, # or "opt" otherwise # OCAMLDEP "ocamldep" # OCAMLLIB the path to the ocaml standard library # OCAMLVERSION the ocaml version number # OCAMLWIN32 "yes"/"no" depending on Sys.os_type = "Win32" # EXE ".exe" if OCAMLWIN32=yes, "" otherwise # check for one particular file of the sources # ADAPT THE FOLLOWING LINE TO YOUR SOURCES! AC_INIT(install.ml.in) # optional arguments AC_ARG_ENABLE(utf8, [ --enable-utf8 enable UTF-8 output (requires ncurses wide char support)], [try_utf8=$enable_utf8], [try_utf8=no]) # Check for Ocaml compilers # we first look for ocamlc in the path; if not present, we fail AC_CHECK_PROG(OCAMLC,ocamlc,ocamlc,no) if test "$OCAMLC" = no ; then AC_MSG_ERROR(Cannot find ocamlc.) fi # we extract Ocaml version number and library path OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` echo "ocaml version is $OCAMLVERSION" OCAMLLIB=`$OCAMLC -v | tail -n 1 | cut -f 4 -d " "` echo "ocaml library path is $OCAMLLIB" # check for sufficient OCAMLVERSION OCAMLMAJORVERSION=`echo $OCAMLVERSION | cut -d '.' -f 1` OCAMLMINORVERSION=`echo $OCAMLVERSION | cut -d '.' -f 2` if test $OCAMLMAJORVERSION -lt 3 ; then AC_MSG_ERROR(Wyrd requires OCaml version 3.08 or greater.) else if test $OCAMLMINORVERSION -lt 8 ; then AC_MSG_ERROR(Wyrd requires OCaml version 3.08 or greater.) fi fi # then we look for ocamlopt; if not present, we issue a warning # if the version is not the same, we also discard it # we set OCAMLBEST to "opt" or "byte", whether ocamlopt is available or not AC_CHECK_PROG(OCAMLOPT,ocamlopt,ocamlopt,no) OCAMLBEST=byte if test "$OCAMLOPT" = no ; then AC_MSG_WARN(Cannot find ocamlopt; bytecode compilation only.) else AC_MSG_CHECKING(ocamlopt version) TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt discarded.) OCAMLOPT=no else AC_MSG_RESULT(ok) OCAMLBEST=opt fi fi # checking for ocamlc.opt AC_CHECK_PROG(OCAMLCDOTOPT,ocamlc.opt,ocamlc.opt,no) if test "$OCAMLCDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlc.opt discarded.) else AC_MSG_RESULT(ok) OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != no ; then AC_CHECK_PROG(OCAMLOPTDOTOPT,ocamlopt.opt,ocamlopt.opt,no) if test "$OCAMLOPTDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVER=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVER" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt.opt discarded.) else AC_MSG_RESULT(ok) OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi # ocamldep should also be present in the path AC_CHECK_PROG(OCAMLDEP,ocamldep,ocamldep,no) if test "$OCAMLDEP" = no ; then AC_MSG_ERROR(Cannot find ocamldep.) fi AC_CHECK_PROG(OCAMLLEX,ocamllex,ocamllex,no) if test "$OCAMLLEX" = no ; then AC_MSG_ERROR(Cannot find ocamllex.) else AC_CHECK_PROG(OCAMLLEXDOTOPT,ocamllex.opt,ocamllex.opt,no) if test "$OCAMLLEXDOTOPT" != no ; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi AC_CHECK_PROG(OCAMLYACC,ocamlyacc,ocamlyacc,no) if test "$OCAMLYACC" = no ; then AC_MSG_ERROR(Cannot find ocamlyacc.) fi # platform AC_MSG_CHECKING(platform) if echo "let _ = Sys.os_type" | ocaml | grep -q Win32; then AC_MSG_RESULT(Win32) OCAMLWIN32=yes EXE=.exe else AC_MSG_RESULT(not Win32) OCAMLWIN32=no EXE= fi # find a C compiler AC_PROG_CC() ORIG_LIBS="$LIBS" ORIG_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CURSES_INCLUDE $ORIG_CPPFLAGS" # check for ncurses AC_MSG_CHECKING(for working ncurses library) if test "$try_utf8" != "no" then LIBS="-lncursesw $ORIG_LIBS" AC_TRY_LINK( [#include ], [initscr(); use_default_colors()], [CURSES_LIB=-lncursesw AC_DEFINE(CURSES_HEADER, , [Defined to ncurses header file])]) fi if test -z "$CURSES_LIB" then LIBS="-lncurses $ORIG_LIBS" AC_TRY_LINK( [#include ], [initscr(); use_default_colors()], [CURSES_LIB=-lncurses AC_DEFINE(CURSES_HEADER, , [Defined to ncurses header file])], [ LIBS="-lncurses $ORIG_LIBS" AC_TRY_LINK( [#include ], [initscr(); use_default_colors()], [CURSES_LIB=-lncurses AC_DEFINE(CURSES_HEADER, , [Defined to ncurses header file])], [ LIBS="-lcurses $ORIG_LIBS" AC_TRY_LINK( [#include ], [initscr(); use_default_colors()], [CURSES_LIB=-lcurses AC_DEFINE(CURSES_HEADER, , [Defined to ncurses header file])], [ LIBS="-lncurses $ORIG_LIBS" AC_TRY_LINK( [#include ], [initscr(); use_default_colors()], [CURSES_LIB=-lcurses AC_DEFINE(CURSES_HEADER, , [Defined to ncurses header file])], ) ]) ]) ]) fi if test -n "$CURSES_LIB" then AC_MSG_RESULT([found in $CURSES_LIB]) else AC_MSG_ERROR([not found]) fi AC_MSG_CHECKING(for ncurses term.h) AC_TRY_COMPILE( [#include ], [TERMTYPE __dummy], [TERM_H_STRING="" AC_DEFINE(CURSES_TERM_H, , [Defined to ncurses term.h file])], [ AC_TRY_COMPILE( [#include ], [TERMTYPE __dummy], [TERM_H_STRING="" AC_DEFINE(CURSES_TERM_H, , [Defined to ncurses term.h file])], [ AC_TRY_COMPILE( [#include ], [TERMTYPE __dummy], [TERM_H_STRING="" AC_DEFINE(CURSES_TERM_H, , [Defined to ncurses term.h file])], ) ]) ]) if test -n "$TERM_H_STRING" then AC_MSG_RESULT([found in $TERM_H_STRING]) else AC_MSG_ERROR([not found]) fi # check whether the detected ncurses has wide char support BOOL_WIDE_CURSES="false" if test -n "$CURSES_LIB" then LIBS="$CURSES_LIB $ORIG_LIBS" if test "$try_utf8" != "no" then AC_MSG_CHECKING(for wide character support in ncurses library) AC_TRY_LINK( [#include #include CURSES_HEADER ], [wchar_t wch = 0; addnwstr(&wch, 1);], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_WIDE_CURSES, 1, [Defined if ncurses library includes wide character support]) BOOL_WIDE_CURSES="true"], [AC_MSG_RESULT(no)]) fi fi CPPFLAGS="$ORIG_CPPFLAGS" LIBS="$ORIG_LIBS" # check Remind version AC_PATH_PROG(REMINDPATH, remind, not found) if test x"$REMINDPATH" != x"not found"; then AC_MSG_CHECKING(remind version) REMINDVERSION=`strings $REMINDPATH | grep 03\.0` AC_MSG_RESULT($REMINDVERSION) REMMAJORVERSION=`echo $REMINDVERSION | cut -d '.' -f 1` REMMINORVERSION=`echo $REMINDVERSION | cut -d '.' -f 2` REMFIXVERSION=`echo $REMINDVERSION | cut -d '.' -f 3` if test $REMMAJORVERSION -lt 3 ; then AC_MSG_WARN(Wyrd requires Remind version 03.01.00 or greater.) else if test $REMMINORVERSION -lt 1 ; then AC_MSG_WARN(Wyrd requires Remind version 03.01.00 or greater.) fi fi else AC_MSG_WARN(Wyrd requires Remind version 03.00.24 or greater.) fi # substitutions to perform AC_SUBST(OCAMLC) AC_SUBST(OCAMLOPT) AC_SUBST(OCAMLDEP) AC_SUBST(OCAMLLEX) AC_SUBST(OCAMLYACC) AC_SUBST(OCAMLBEST) AC_SUBST(OCAMLVERSION) AC_SUBST(OCAMLLIB) AC_SUBST(OCAMLWIN32) AC_SUBST(EXE) AC_SUBST(CURSES_HEADER) AC_SUBST(CURSES_TERM_H) AC_SUBST(CURSES_LIB) AC_SUBST(BOOL_WIDE_CURSES) AC_SUBST(DEFS) AC_SUBST(CC) AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) # Finally create the Makefile from Makefile.in AC_OUTPUT(Makefile install.ml) chmod a-w Makefile # arch-tag: DO_NOT_CHANGE_3852958f-9da5-4ee1-8a22-ac63ac00aaac wyrd-1.4.4/interface.ml0000644000175000017500000001513510757447265013511 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* interface.ml * This file defines the data structure (a record) that stores the * interface state. *) open Curses;; open Rcfile;; exception Not_handled;; (* help_win is provided as an option, because it may be dropped if * the screen width is too small *) type screen_t = { stdscr : window; lines : int; cols : int; help_win : window; hw_cols : int; timed_win : window; tw_lines : int; tw_cols : int; calendar_win : window; cw_lines : int; cw_cols : int; untimed_win : window; uw_lines : int; uw_cols : int; msg_win : window; mw_lines : int; mw_cols : int; err_win : window; ew_lines : int; ew_cols : int } type zoom_t = Hour | HalfHour | QuarterHour type side_t = Left | Right (* keep track of information needed for a line of * the timed reminders window *) type timed_lineinfo_t = { tl_filename : string; tl_linenum : string; tl_timestr : string; tl_msg : string; tl_start : float } (* keep track of information needed for a line of * the untimed reminders window *) type untimed_lineinfo_t = { ul_filename : string; ul_linenum : string; ul_msg : string } type extended_mode_t = ExtendedSearch | ExtendedGoto | ExtendedQuick type entry_mode_t = Normal | Extended of extended_mode_t (* everything you need to know about the interface state goes in this variable *) type interface_state_t = { version : string; (* program version string *) scr : screen_t; (* curses screen with two or three subwindows *) run_wyrd : bool; (* exit when run_wyrd becomes false *) top_timestamp : float; (* controls what portion of the schedule is viewable *) top_untimed : int; (* controls what portion of untimed reminders are viewable *) top_desc : int; (* controls what portion of the reminder descriptions are viewable *) selected_side : side_t; (* controls which window has the focus *) left_selection : int; (* controls which element of the left window is selected *) right_selection : int; (* controls which element of the right window is selected *) zoom_level : zoom_t; (* controls the resolution of the timed window *) timed_lineinfo : timed_lineinfo_t list array; (* information about the lines of the timed reminder window *) untimed_lineinfo : untimed_lineinfo_t option array; (* same as above, for untimed window *) len_untimed : int; (* number of entries in the untimed reminders list *) search_regex : Str.regexp; (* most recent search string *) extended_input : string; (* buffer to hold search/goto/quick event info *) entry_mode : entry_mode_t; (* decides which mode the interface is in *) last_timed_refresh: float; (* the last time the timed window had a complete refresh *) rem_buffer : string; (* buffer that acts as a clipboard for REM strings *) track_home : bool; (* true if cursor position should "stick" to current time *) resize_failed_win : window option (* if a resize fails, this holds a window pointer for an error msg. *) } (* round to the nearest displayed time value *) let round_time zoom t = match zoom with |Hour -> { t with Unix.tm_sec = 0; Unix.tm_min = 0 } |HalfHour -> { t with Unix.tm_sec = 0; Unix.tm_min = if t.Unix.tm_min >= 30 then 30 else 0 } |QuarterHour -> { t with Unix.tm_sec = 0; Unix.tm_min = if t.Unix.tm_min >= 45 then 45 else if t.Unix.tm_min >= 30 then 30 else if t.Unix.tm_min >= 15 then 15 else 0 } (* create and initialize an interface with default settings *) let make (std : screen_t) = let curr_time = Unix.localtime ((Unix.time ()) -. 60. *. 60.) in let (rounded_time, _) = Unix.mktime (round_time Hour curr_time) in { version = Version.version; scr = std; run_wyrd = true; top_timestamp = if !Rcfile.center_cursor then rounded_time -. 60.0 *. 60.0 *. (float_of_int ((std.tw_lines / 2) - 2)) else rounded_time -. 60.0 *. 60.0; top_untimed = 0; top_desc = 0; selected_side = Left; left_selection = if !Rcfile.center_cursor then (std.tw_lines / 2) - 1 else 2; right_selection = 1; zoom_level = Hour; timed_lineinfo = Array.make std.tw_lines []; untimed_lineinfo = Array.make std.uw_lines None; len_untimed = 0; search_regex = Str.regexp ""; extended_input = ""; entry_mode = Normal; last_timed_refresh = 0.0; rem_buffer = ""; track_home = !Rcfile.home_sticky; resize_failed_win = None } (* time increment in float seconds *) let time_inc (iface : interface_state_t) = match iface.zoom_level with | Hour -> 60.0 *. 60.0 | HalfHour -> 30.0 *. 60.0 | QuarterHour -> 15.0 *. 60.0 (* time increment in int minutes *) let time_inc_min (iface : interface_state_t) = match iface.zoom_level with | Hour -> 60 | HalfHour -> 30 | QuarterHour -> 15 let timestamp_of_line iface line = iface.top_timestamp +. ((float_of_int line) *. (time_inc iface)) (* arch-tag: DO_NOT_CHANGE_2e912989-cdb2-498a-9bb3-b6d76e94f3a5 *) wyrd-1.4.4/ChangeLog0000644000175000017500000002751610757447264012776 0ustar paulpaulWyrd ChangeLog -------------------------------------------------------------------------------- 2008-02-21 Released 1.4.4. Fixed an instance of insecure tempfile creation. This addresses a security vulnerability that had the potential to cause data loss. 2007-08-17 Released 1.4.3. Modified the configure script to support weird locations of ncurses term.h . Deprecated the 'calendar_selection' colorable object. For consistency with the rest of the Wyrd interface, the selected calendar day is now rendered in reverse video. Added the 'untimed_bold' configuration variable for selecting between normal and boldface rendering of untimed reminders. Added support for remind's 'filedir()' function within INCLUDE directives, for those who like to "INCLUDE [filedir()]/some-extra-reminders". Thanks to Stefan Wehr for the patch. Implemented more extensive shell-expansion of filenames specified within wyrdrc, enabling the use of idioms like 'set reminders_file="$DOT_REMINDERS"'. 2007-08-16 Added support for Remind 3.1.0 advance warning of reminders throughout the Wyrd interface, enabled via the 'advance_warning' configuration variable. 2007-08-15 Support new Remind 3.1.0 date formatting. 2007-05-25 Released 1.4.2. 2007-04-28 Added the untimed_window_width rcfile option, which lets the user set the width of the windows on the right side of the display. Tweaked the resize handler so Wyrd does not completely die when the terminal is resized too small. Made modifications to support rendering UTF-8 reminders (requires ncurses built with wide char support) 2007-04-23 Added the home_sticky option, allowing the cursor position to automatically track the current time. Added command-line option to append reminders using the natural language parser. 2007-04-22 Eliminated dependence on Bash-style tilde expansion. 2006-07-16 Released 1.4.1. 2006-07-13 Fixed the "blank screen" bug that resulted from I/O buffering synchronization issues. 2006-07-05 Fixed an error with registering certain color schemes. 2006-07-03 Corrected typo in the word "July". 2006-07-02 Added the 'quick_date_US' option, allowing users to choose between "month first" or "day first" conventions when entering quick reminders with numeric dates. 2006-06-26 Released 1.4.0. Added the 'default' color specifier, which accesses the default terminal foreground and background colors. (A 'default' background color also enables background transparency on terminal emulators which support it.) Reduced the minimum terminal height to 23 lines, so screen(1) users should always be able to use a status bar. Fixed a bug that caused events with zero duration to overlap. Implemented "quick reminder" command, allowing the user to quickly describe an event using natural language (USA English, at least). 2006-05-02 Changed the substitution strings used within wyrdrc, to prevent namespace collisions with Remind's substitution filter. (This breaks compatibility with old wyrdrc files.) 2006-04-24 Corrected a bug in the chronological ordering of untimed reminders. 2006-04-22 Added some checks to prevent scrolling outside the acceptable date range. 2006-04-20 Implemented optional ISO-8601 week numbering. Made some corrections to the coloring code. Code cleanup. 2006-04-13 Remind errors are now handled somewhat sanely. 2006-02-24 Released 1.3.0. Set the default editor to $EDITOR. Errors are now detected when launching an editor. Improved the Remind version detection within the build script. 2006-02-04 Implemented the 'goto' operation, which allows the user to manually enter a date and then jump immediately to that day. The boolean option 'goto_big_endian' selects whether dates are represented using YYYYMMDD or DDMMYYYY format. 2006-02-03 Implemented the 'cut', 'copy', and 'paste' operations, which provide a convenient interface to duplicate or reschedule reminders. 2006-02-01 The 'edit_any' command now spawns a selection dialog only when the user has multiple reminder files. 2005-11-20 Released 1.2.0. Added the 'busy_algorithm' and 'untimed_duration' configuration variables, which can be used to set the algorithm for determining the "busy" level for each day on the month calendar. There are two algorithms to choose from: count number of triggered reminders per day, or count number of hours of reminders per day. The configuration script now checks for acceptable versions of OCaml and Remind. 2005-10-30 Corrected the build script to support parallel make once again. Replaced the deprecated "tail -1" syntax in the configure script. 2005-10-15 Fixed an off-by-one error in the resize handler, which could cause the Wyrd status line to appear on two different lines. 2005-10-02 Fixed a bug that could cause find_next and next_reminder to fail. 2005-09-30 Added the configuration variable 'remind_command', which can be used to specify the Remind executable. 2005-09-18 The current date and time are now highlighted within the month calendar and timed reminders window, according to the color values set for 'calendar_today' and 'timed_current'. (The selected date is now highlighted in the calendar window according to the 'calendar_selection' setting, rather than the 'calendar_today' setting.) 2005-09-17 If there are multiple reminders listed in the message window, they are now sorted by starting timestamp. Wyrd now chooses tempfile names that are unique for each user. Added the 'help' command, which generates a list of all keybindings. 2005-09-21 Released 1.1.1. 2005-09-20 Updated the build script to support the NetBSD environment. 2005-09-17 Implemented a built-in calendar layout algorithm, and removed the dependence on cal(1). 2005-09-15 Released 1.1.0. Implemented the 'next_reminder' command, which jumps forward to the next reminder in chronological order. Made 'search_next' more robust--certain edge cases are now handled better. 2005-09-13 Improved the alignment of timestamps in the reminder description window. Fixed a typo in the short string representation for Tuesday. Implemented the 'view_week' and 'view_month' commands, which view Remind's formatted weekly or monthly calendars for the selected date. Implemented the 'edit_any' command and associated 'edit_any_template', which can be used to edit a reminder file without selecting any particular reminder. The untimed reminders window now accepts focus even when there are no untimed reminders. Executing the 'edit' command on a blank timeslot now creates a new timed reminder. Hitting 'edit' on a blank untimed reminders list creates a new untimed reminder. Added support for 'nodisplay' and 'noweight' TAG parameters, which can be used to suppress display of reminders or give them no weight when determining the "busy level" colorations on the month calendar. Removed nonsensical DURATION specifiers from default weekly and monthly untimed reminder templates. Added the 'center_cursor' option, which can be used to fix the cursor in the center of the timed reminders window while scrolling. 2005-09-12 Fixed an assertion failure caused by entering an unprintable character in a search string. 2005-06-23 Released 1.0.0. 2005-06-22 Added a screen refresh function. 2005-06-21 Implemented overlapping timed reminders and associated routines for handling multiple reminders in a single timeslot. Colorable object 'timed_reminder' has been deprecated in favor of 'timed_reminder1' through 'timed_reminder4', so that overlapping reminders can be given different colors. 2005-06-20 Corrected the disappearing cursor bug associated with jumping between days with differing numbers of untimed reminders. 2005-05-04 Released 0.3.0. Converted the documentation to LaTeX format, with PDF, HTML, and manpage targets. Added "new_*_dialog" commands for creating new reminders. These commands will generate a selection dialog for choosing which reminder file to add the new reminder to. 2005-05-03 Added a bunch of generic user-defined reminder templates. By default, some of these are configured to generate weekly and monthly reminders. Added a beep and error message when pressing an unbound key. Start and end times in the description window had been rendered according to the value of schedule_12_hour; now they are rendered according to the value of new variable description_12_hour . 2005-04-29 Fixed a rare bug that could cause timed reminders to become temporarily invisible at month boundaries. Optimized rendering of timed reminders window when scrolling (should be a little smoother now on slow hardware). 2005-04-26 Released 0.2.0. 2005-04-25 Made colors configurable via the rcfile. Made time representation (12/24 hour) configurable via the rcfile. Implemented external viewing of triggered reminders ("rem -q -g") via less(1). Added a resize handler. 2005-04-23 Added a configuration variable to switch the first day of the week between Sunday and Monday. Wyrd now accepts an optional reminders file as a command-line parameter. 2005-04-16 Released 0.1.3. A more suitable error message is generated when trying to run Wyrd on terminals without color support. Wyrd now discards exceptions due to errors on curs_set(), which is not supported in all terminals. Made installation script portable to BSD install(1). 2005-04-15 Released 0.1.2. Upon further investigation, cpp appears to be completely broken on OS X. Wyrd now ships with pre-preprocessed ML files. Released 0.1.1. Changed invocations of 'cpp' to 'cpp -P' to correct compilation errors on OS X, maybe others. Released 0.1.0. # arch-tag: DO_NOT_CHANGE_0a925fdb-a0fa-4330-a560-dd31770ca22c wyrd-1.4.4/interface_main.ml0000644000175000017500000024006510757447265014517 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* interface_main.ml * This file has the bulk of the implementation of the curses-based interface, * including the main program loop that grabs keypresses and processes them. * The screen rendering code is found in interface_draw.ml . *) open Curses open Printf open Interface open Interface_draw exception Interrupt_exception exception Template_undefined of string type reminder_type_t = Timed | Untimed | General of int (*******************************************************************) (* RESIZE HANDLER *) (*******************************************************************) (* create the (new) windows corresponding to the different areas of the screen *) (* note: to get around curses issues with addch on the last character of the * last row, all windows are created one line too long. The last lines are * never used. (Is this the best way to do things?) *) let create_windows screen = let height, width = get_size () in let cal_height = 10 and cal_width = if !Rcfile.untimed_window_width < 34 then 34 else if !Rcfile.untimed_window_width > width - 40 then width - 40 else !Rcfile.untimed_window_width in let msg_height = 6 in let err_height = 1 in let timed_height = height - 1 - msg_height - err_height and timed_width = width - cal_width and untimed_height = height - 1 - msg_height - err_height - cal_height and untimed_width = cal_width in if height >= 23 then if width >= 80 then { stdscr = screen; lines = height; cols = width; help_win = newwin 2 width 0 0; hw_cols = width; timed_win = newwin (succ timed_height) timed_width 1 0; tw_lines = timed_height; tw_cols = timed_width; calendar_win = newwin (succ cal_height) cal_width 1 timed_width; cw_lines = cal_height; cw_cols = cal_width; untimed_win = newwin (succ untimed_height) untimed_width (1 + cal_height) timed_width; uw_lines = untimed_height; uw_cols = untimed_width; msg_win = newwin (succ msg_height) width (1 + timed_height) 0; mw_lines = msg_height; mw_cols = width; err_win = newwin err_height width (pred height) 0; ew_lines = err_height; ew_cols = pred width (* don't print in last line of the last column *) } else (endwin (); failwith "Wyrd requires at least an 80 column window.") else (endwin (); failwith "Wyrd requires at least a 23 line window.") (* wresize all the child windows via wresize and mvwin *) let resize_subwins iface = let height, width = get_size () in let cal_height = 10 and cal_width = if !Rcfile.untimed_window_width < 34 then 34 else if !Rcfile.untimed_window_width > width - 40 then width - 40 else 40 in let msg_height = 6 in let err_height = 1 in let timed_height = height - 1 - msg_height - err_height and timed_width = width - cal_width and untimed_height = height - 1 - msg_height - err_height - cal_height and untimed_width = cal_width in let new_scr = if height >= 23 then if width >= 80 then {iface.scr with lines = height; cols = width; hw_cols = width; tw_lines = timed_height; tw_cols = timed_width; cw_lines = cal_height; cw_cols = cal_width; uw_lines = untimed_height; uw_cols = untimed_width; mw_lines = msg_height; mw_cols = width; ew_lines = err_height; ew_cols = pred width } else (endwin (); failwith "Wyrd requires at least an 80 column window.") else (endwin (); failwith "Wyrd requires at least a 23 line window.") in assert (wresize new_scr.help_win 2 width); assert (wresize new_scr.timed_win (succ timed_height) timed_width); assert (wresize new_scr.calendar_win (succ cal_height) cal_width); assert (mvwin new_scr.calendar_win 1 timed_width); assert (wresize new_scr.untimed_win (succ untimed_height) untimed_width); assert (mvwin new_scr.untimed_win (1 + cal_height) timed_width); assert (wresize new_scr.msg_win (succ msg_height) width); assert (mvwin new_scr.msg_win (1 + timed_height) 0); assert (wresize new_scr.err_win err_height width); assert (mvwin new_scr.err_win (pred height) 0); new_scr (* Parse a natural language event description and append * the result to the specified reminders file. *) let append_quick_event event_spec remfile = let (rem_spec, description) = Time_lang.parse_natural_language_event event_spec in let remline = begin match rem_spec with | Time_lang.Timed (start, finish) -> let date_s = Printf.sprintf "REM %s %d %d " (Utility.string_of_tm_mon start.Unix.tm_mon) start.Unix.tm_mday (start.Unix.tm_year + 1900) in let start_s = Printf.sprintf "AT %.2d:%.2d " start.Unix.tm_hour start.Unix.tm_min in let duration_s = if start <> finish then let (start_ts, _) = Unix.mktime start and (finish_ts, _) = Unix.mktime finish in let dur = int_of_float ((finish_ts -. start_ts) /. 60.0) in Printf.sprintf "DURATION %d:%.2d " (dur / 60) (dur mod 60) else "" in date_s ^ start_s ^ duration_s ^ "MSG " ^ description ^ "\n" | Time_lang.Untimed timespec -> let date_s = Printf.sprintf "REM %s %d %d " (Utility.string_of_tm_mon timespec.Unix.tm_mon) timespec.Unix.tm_mday (timespec.Unix.tm_year + 1900) in date_s ^ "MSG " ^ description ^ "\n" end in (* append the remline to the reminders file *) let remfile_channel = open_out_gen [Open_append; Open_creat; Open_text] 416 (Utility.expand_file remfile) in output_string remfile_channel remline; close_out remfile_channel; (rem_spec, remline) (* refresh the screen *) let handle_refresh (iface : interface_state_t) reminders = let _ = wtouchln iface.scr.help_win 0 1 true in let _ = wtouchln iface.scr.timed_win 0 iface.scr.tw_lines true in let _ = wtouchln iface.scr.calendar_win 0 iface.scr.cw_lines true in let _ = wtouchln iface.scr.untimed_win 0 iface.scr.uw_lines true in let _ = wtouchln iface.scr.msg_win 0 iface.scr.mw_lines true in draw_help iface; let new_iface = draw_timed iface reminders.Remind.all_timed in draw_date_strip new_iface; draw_calendar new_iface reminders; let new_iface = draw_untimed new_iface reminders.Remind.curr_untimed in if String.length reminders.Remind.remind_error > 0 then let _ = beep () in () else (); draw_error new_iface reminders.Remind.remind_error false; (new_iface, reminders) (* handle a curses resize *) let handle_resize (iface : interface_state_t) reminders = endwin (); begin match iface.resize_failed_win with | None -> () | Some w -> let _ = delwin w in () end; begin try let new_scr = resize_subwins iface in let resized_iface = { iface with scr = new_scr; top_untimed = 0; left_selection = if !Rcfile.center_cursor then (iface.scr.tw_lines / 2) - 1 else 1; right_selection = 1; timed_lineinfo = Array.make new_scr.tw_lines []; resize_failed_win = None } in begin try assert (curs_set 0) with _ -> () end; clear (); assert (refresh ()); handle_refresh resized_iface reminders with Failure s -> (* Create a new full-screen window where we can * paint an error message. *) let w = newwin 0 0 0 0 in erase (); assert (mvwaddstr w 0 0 s); assert (wnoutrefresh w); assert (doupdate ()); ({iface with resize_failed_win = Some w}, reminders) end (* Any time a new item is selected, the reminders * record needs updating and the screen need redrawing *) let handle_selection_change iface reminders track_home_setting = let new_reminders = Remind.update_reminders reminders (timestamp_of_line iface iface.left_selection) in let new_iface = draw_untimed iface new_reminders.Remind.curr_untimed in let new_iface = draw_timed new_iface new_reminders.Remind.all_timed in draw_date_strip new_iface; draw_calendar new_iface new_reminders; draw_error new_iface "" false; ({new_iface with track_home = track_home_setting}, new_reminders) (* Same as previous, but without calling draw_timed () or * draw_date_strip (). Optimization for the scrolling case. *) let handle_selection_change_scroll iface reminders track_home_setting = let new_reminders = Remind.update_reminders reminders (timestamp_of_line iface iface.left_selection) in draw_calendar iface new_reminders; let new_iface = draw_untimed iface new_reminders.Remind.curr_untimed in draw_error new_iface "" false; ({new_iface with track_home = track_home_setting}, new_reminders) (* handle a "scroll down" event when the timed window is focused * and the center_cursor option is turned on *) let handle_scrolldown_timed_center (iface : interface_state_t) reminders = let second_timestamp = timestamp_of_line iface 1 in let iface2 = { iface with top_timestamp = second_timestamp } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* use a curses scroll operation to shift up the timed window *) assert (wscrl new_iface.scr.timed_win 1); (* adjust lineinfo array to compensate for scrolling *) Array.blit iface.timed_lineinfo 1 iface.timed_lineinfo 0 (pred (Array.length iface.timed_lineinfo)); (* do a two-line update to recenter the cursor *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed (iface.left_selection - 1) 2 in (* draw in the new line at the bottom of the screen *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed (iface.scr.tw_lines - 1) 1 in draw_date_strip new_iface; (new_iface, new_reminders) (* handle a "scroll down" event when the timed window is focused * and the center_cursor option is turned off *) let handle_scrolldown_timed_nocenter (iface : interface_state_t) reminders = if iface.left_selection < pred iface.scr.tw_lines then begin (* case 1: only the cursor moves *) let iface2 = { iface with left_selection = succ iface.left_selection } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* make a two-line update to erase and redraw the cursor *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed iface.left_selection 2 in (new_iface, new_reminders) end else begin (* case 2: the entire timed window scrolls *) let second_timestamp = timestamp_of_line iface 1 in let iface2 = { iface with top_timestamp = second_timestamp } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* use a curses scroll operation to shift up the timed window *) assert (wscrl new_iface.scr.timed_win 1); (* adjust lineinfo array to compensate for scrolling *) Array.blit iface.timed_lineinfo 1 iface.timed_lineinfo 0 (pred (Array.length iface.timed_lineinfo)); (* do a two-line update to erase the cursor and draw in the * new line at the bottom of the screen *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed (iface.scr.tw_lines - 2) 2 in draw_date_strip new_iface; (new_iface, new_reminders) end (* handle a "scroll down" event when the timed window is focused *) let handle_scrolldown_timed (iface : interface_state_t) reminders = (* watch out for y2k38 *) let selected_day = Unix.localtime (iface.top_timestamp +. (float_of_int (succ iface.left_selection)) *. (time_inc iface)) in if (selected_day.Unix.tm_year + 1900) > 2037 then begin draw_error iface "requested year is out of range." false; assert (doupdate ()); (iface, reminders) end else let iface = { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } in if !Rcfile.center_cursor then handle_scrolldown_timed_center iface reminders else handle_scrolldown_timed_nocenter iface reminders (* handle a "scroll down" event when the untimed window is focused *) let handle_scrolldown_untimed (iface : interface_state_t) reminders = if iface.right_selection < pred iface.scr.uw_lines then begin if iface.right_selection < iface.len_untimed - iface.top_untimed then begin let new_iface = { iface with right_selection = succ iface.right_selection } in handle_selection_change new_iface reminders false end else (iface, reminders) end else begin if iface.right_selection < iface.len_untimed - iface.top_untimed then begin let new_iface = { iface with top_untimed = succ iface.top_untimed } in handle_selection_change new_iface reminders false end else (iface, reminders) end (* handle a "scroll up" event when the timed window is focused * and the center_cursor option is turned on *) let handle_scrollup_timed_center (iface : interface_state_t) reminders = let prev_timestamp = timestamp_of_line iface (-1) in let iface2 = { iface with top_timestamp = prev_timestamp } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* use a curses scroll operation to shift up the timed window *) assert (wscrl new_iface.scr.timed_win (-1)); (* adjust lineinfo array to compensate for scrolling *) Array.blit iface.timed_lineinfo 0 iface.timed_lineinfo 1 (pred (Array.length iface.timed_lineinfo)); (* do a two-line update to recenter the cursor *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed iface.left_selection 2 in (* draw in the new top line of the schedule *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed 0 1 in draw_date_strip new_iface; (new_iface, new_reminders) (* handle a "scroll up" event when the timed window is focused * and the center_cursor option is turned off *) let handle_scrollup_timed_nocenter (iface : interface_state_t) reminders = if iface.left_selection > 0 then begin (* case 1: only the cursor moves *) let iface2 = { iface with left_selection = pred iface.left_selection } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* make a two-line update to erase and redraw the cursor *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed (pred iface.left_selection) 2 in (new_iface, new_reminders) end else begin (* case 2: the entire timed window scrolls *) let prev_timestamp = timestamp_of_line iface (-1) in let iface2 = { iface with top_timestamp = prev_timestamp } in let (new_iface, new_reminders) = handle_selection_change_scroll iface2 reminders false in (* use a curses scroll operation to shift up the timed window *) assert (wscrl new_iface.scr.timed_win (-1)); (* adjust lineinfo array to compensate for scrolling *) Array.blit iface.timed_lineinfo 0 iface.timed_lineinfo 1 (pred (Array.length iface.timed_lineinfo)); (* do a two-line update to erase the cursor and draw in the * new line at the bottom of the screen *) let new_iface = draw_timed_try_window new_iface new_reminders.Remind.all_timed 0 2 in draw_date_strip new_iface; (new_iface, new_reminders) end (* handle a "scroll up" event when the timed window is focused *) let handle_scrollup_timed (iface : interface_state_t) reminders = (* watch out for scrolling out of Remind date range *) let selected_day = Unix.localtime iface.top_timestamp in if (selected_day.Unix.tm_year + 1900) < 1991 then begin draw_error iface "requested year is out of range." false; assert (doupdate ()); (iface, reminders) end else let iface = { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } in if !Rcfile.center_cursor then handle_scrollup_timed_center iface reminders else handle_scrollup_timed_nocenter iface reminders (* handle a "scroll up" event when the untimed window is focused *) let handle_scrollup_untimed (iface : interface_state_t) reminders = if iface.right_selection > 1 then let new_iface = { iface with right_selection = pred iface.right_selection } in handle_selection_change new_iface reminders new_iface.track_home else if iface.top_untimed > 0 then let new_iface = { iface with top_untimed = pred iface.top_untimed } in handle_selection_change new_iface reminders new_iface.track_home else (iface, reminders) (* handle a jump to a different day *) let handle_jump (iface : interface_state_t) reminders jump_func = (* new timestamp for top line of screen *) let temp = Unix.localtime iface.top_timestamp in let next_tm = jump_func temp in let (next_ts, normalized_tm) = Unix.mktime next_tm in (* new timestamp for bottom line of screen *) let temp2 = Unix.localtime (iface.top_timestamp +. (float_of_int (succ iface.left_selection)) *. (time_inc iface)) in let next_tm2 = jump_func temp2 in let (_, normalized_tm2) = Unix.mktime next_tm2 in (* check that the date range is OK for both Remind and *nix *) if (normalized_tm.Unix.tm_year + 1900) < 1991 || (normalized_tm2.Unix.tm_year + 1900) > 2037 then begin draw_error iface "requested year is out of range." false; assert (doupdate ()); (iface, reminders) end else let new_iface = { iface with top_timestamp = next_ts; top_desc = 0 } in handle_selection_change new_iface reminders false (* handle switching window focus *) let handle_switch_focus (iface : interface_state_t) reminders = let new_iface = match iface.selected_side with |Left -> {iface with selected_side = Right} |Right -> {iface with selected_side = Left} in handle_selection_change new_iface reminders new_iface.track_home (* handle switching to the current timeslot *) let handle_home (iface : interface_state_t) reminders = let curr_time = Unix.localtime ((Unix.time ()) -. (time_inc iface)) in let (rounded_time, _) = Unix.mktime (round_time iface.zoom_level curr_time) in let new_iface = { iface with top_timestamp = if !Rcfile.center_cursor then rounded_time -. (time_inc iface) *. (float_of_int ((iface.scr.tw_lines / 2) - 2)) else rounded_time -. (time_inc iface) *. 1.; top_desc = 0; selected_side = Left; left_selection = if !Rcfile.center_cursor then (iface.scr.tw_lines / 2) - 1 else 2; right_selection = 1 } in handle_selection_change new_iface reminders true (* handle a zoom keypress *) let handle_zoom (iface : interface_state_t) reminders = let new_iface = let curr_ts = timestamp_of_line iface iface.left_selection in let curr_tm = Unix.localtime curr_ts in let hour_tm = { curr_tm with Unix.tm_sec = 0; Unix.tm_min = 0 } in let (hour_ts, _) = Unix.mktime hour_tm in match iface.zoom_level with |Hour -> let new_top = curr_ts -. (60.0 *. 30.0 *. (float_of_int iface.left_selection)) in { iface with top_timestamp = new_top; top_desc = 0; zoom_level = HalfHour } |HalfHour -> let new_top = curr_ts -. (60.0 *. 15.0 *. (float_of_int iface.left_selection)) in { iface with top_timestamp = new_top; top_desc = 0; zoom_level = QuarterHour } |QuarterHour -> let new_top = hour_ts -. (60.0 *. 60.0 *. (float_of_int iface.left_selection)) in { iface with top_timestamp = new_top; top_desc = 0; zoom_level = Hour } in if new_iface.track_home then handle_home new_iface reminders else let new_iface = draw_timed new_iface reminders.Remind.all_timed in draw_date_strip new_iface; (new_iface, reminders) (* handle creation of a new timed or untimed reminder *) let handle_new_reminder (iface : interface_state_t) reminders rem_type remfile = let ts = timestamp_of_line iface iface.left_selection in let tm = Unix.localtime ts in (* take care of the substitution characters in remline templates *) let substitute template = let rec substitute_aux subst_list s = match subst_list with |[] -> s |(regex, replacement) :: tail -> let new_s = Str.global_replace regex replacement s in substitute_aux tail new_s in substitute_aux [ (Str.regexp "%monname%", Utility.string_of_tm_mon tm.Unix.tm_mon); (Str.regexp "%mon%", string_of_int (succ tm.Unix.tm_mon)); (Str.regexp "%mday%", string_of_int tm.Unix.tm_mday); (Str.regexp "%year%", string_of_int (tm.Unix.tm_year + 1900)); (Str.regexp "%hour%", Printf.sprintf "%.2d" tm.Unix.tm_hour); (Str.regexp "%min%", Printf.sprintf "%.2d" tm.Unix.tm_min); (Str.regexp "%wdayname%", Utility.string_of_tm_wday tm.Unix.tm_wday); (Str.regexp "%wday%", string_of_int tm.Unix.tm_wday) ] template in try let remline = match rem_type with | Timed -> substitute !Rcfile.timed_template | Untimed -> substitute !Rcfile.untimed_template | General x -> let template_status = match x with | 0 -> (!Rcfile.template0, "template0") | 1 -> (!Rcfile.template1, "template1") | 2 -> (!Rcfile.template2, "template2") | 3 -> (!Rcfile.template3, "template3") | 4 -> (!Rcfile.template4, "template4") | 5 -> (!Rcfile.template5, "template5") | 6 -> (!Rcfile.template6, "template6") | 7 -> (!Rcfile.template7, "template7") | 8 -> (!Rcfile.template8, "template8") | 9 -> (!Rcfile.template9, "template9") | _ -> failwith ("unexpected template number " ^ (string_of_int x) ^ " in handle_new_reminder") in begin match template_status with | (None, template_str) -> raise (Template_undefined template_str) | (Some t, _) -> substitute t end in (* append the remline to the reminders file *) let remfile_channel = open_out_gen [Open_append; Open_creat; Open_text] 416 remfile in output_string remfile_channel remline; close_out remfile_channel; (* open the reminders file in an editor *) let filename_sub = Str.regexp "%file%" in let command = Str.global_replace filename_sub remfile !Rcfile.edit_new_command in def_prog_mode (); endwin (); let editor_process_status = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; let r = Remind.create_three_month iface.top_timestamp in (* if the untimed list has been altered, change the focus to * the first element of the list *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } else iface in begin match editor_process_status with | Unix.WEXITED return_code -> if return_code <> 0 then begin let (new_iface, r) = handle_refresh new_iface r in let _ = beep () in draw_error new_iface "Error when launching editor; configure a different editor in ~/.wyrdrc ." false; assert (doupdate ()); (new_iface, r) end else handle_refresh new_iface r | _ -> let (new_iface, r) = handle_refresh new_iface r in draw_error new_iface "Editor process was interrupted." false; assert (doupdate ()); (new_iface, r) end with Template_undefined template_str -> draw_error iface (template_str ^ " is undefined.") false; assert (doupdate ()); (iface, reminders) (* Search forward for the next occurrence of the current search regex. * * First find the date of the occurrence, by matching on the output of 'remind * -n'. For that date, recompute timed and untimed reminder lists. Filter the * timed and untimed reminder lists to get only the entries falling on the * occurrence date. Search through the filtered timed list first, and locate * the first entry that matches the regex (if any). Then search through the * filtered untimed list, and locate the first entry that matches the regex (if any). * If only one of the lists has a match, return that one; if both lists have a match, * return the one with the earlier timestamp. * Finally, reconfigure the iface record to highlight the matched entry. * * If the user has advance_warning enabled, the algorithm becomes more complicated. * After finding the correct search date, we have to locate reminders that are * present when advance warnings are *suppressed*. This is accomplished by * searching through the reminders list with advanced warning suppressed, then * searching for an *identical string* within the reminders list with advanced * warning enabled. * * The saved search regex can be ignored by providing Some regex as the * override_regex parameter. * * FIXME: This function is about five times too large. *) let handle_find_next (iface : interface_state_t) reminders override_regex = let search_regex = match override_regex with |None -> iface.search_regex |Some regex -> regex in try (* Note: selected_ts is the timestamp of the next timeslot, minus one second. * This ensures that searching begins immediately after the current * selection. *) let selected_ts = (timestamp_of_line iface (succ iface.left_selection)) -. 1.0 in let occurrence_time = Remind.find_next search_regex selected_ts in (* Reminders with advance warning included *) let no_advw_reminders= if !Rcfile.advance_warning then Remind.create_three_month ~suppress_advwarn:true occurrence_time else Remind.update_reminders reminders occurrence_time in (* Reminders with advance warning suppressed *) let advw_reminders = if !Rcfile.advance_warning then Remind.update_reminders reminders occurrence_time else no_advw_reminders in let occurrence_tm = Unix.localtime occurrence_time in let temp1 = { occurrence_tm with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0 } in let temp2 = { occurrence_tm with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0; Unix.tm_mday = succ occurrence_tm.Unix.tm_mday } in let (day_start_ts, _) = Unix.mktime temp1 in let (day_end_ts, _) = Unix.mktime temp2 in (* filter functions to determine reminders falling on the occurrence day *) let is_current_untimed rem = rem.Remind.ur_start >= day_start_ts && rem.Remind.ur_start < day_end_ts in let is_current_timed rem = rem.Remind.tr_start >= day_start_ts && rem.Remind.tr_start < day_end_ts in (* test the untimed reminders list, with advanced warnings enabled, * for entries that match the specified string *) let rec check_untimed_advw match_string untimed n timed_match = match untimed with |[] -> begin match timed_match with |None -> let _ = beep () in draw_error iface "search expression not found." false; assert (doupdate ()); (iface, reminders) |Some (timed_match_ts, timed_match_iface) -> handle_selection_change timed_match_iface advw_reminders false end |urem :: tail -> begin try if urem.Remind.ur_start > selected_ts && urem.Remind.ur_msg = match_string then let tm = Unix.localtime urem.Remind.ur_start in let (rounded_time, _) = Unix.mktime (round_time iface.zoom_level tm) in let new_iface = (* take care of highlighting the correct untimed reminder *) if n >= iface.scr.uw_lines then if !Rcfile.center_cursor then { iface with top_timestamp = rounded_time -. (time_inc iface) *. (float_of_int (iface.scr.tw_lines / 2 - 1)); top_untimed = n - iface.scr.uw_lines + 1; top_desc = 0; left_selection = (iface.scr.tw_lines / 2) - 1; right_selection = pred iface.scr.uw_lines; selected_side = Right } else { iface with top_timestamp = rounded_time; top_untimed = n - iface.scr.uw_lines + 1; top_desc = 0; left_selection = 0; right_selection = pred iface.scr.uw_lines; selected_side = Right } else if !Rcfile.center_cursor then { iface with top_timestamp = rounded_time -. (time_inc iface) *. (float_of_int (iface.scr.tw_lines / 2 - 1)); top_untimed = 0; top_desc = 0; left_selection = (iface.scr.tw_lines / 2) - 1 ; right_selection = n; selected_side = Right } else { iface with top_timestamp = rounded_time; top_untimed = 0; top_desc = 0; left_selection = 0; right_selection = n; selected_side = Right } in (* choose between the timed reminder match and the untimed reminder match *) begin match timed_match with |None -> handle_selection_change new_iface advw_reminders false |Some (timed_match_ts, timed_match_iface) -> if timed_match_ts < urem.Remind.ur_start then handle_selection_change timed_match_iface advw_reminders false else handle_selection_change new_iface advw_reminders false end else raise Not_found with Not_found -> check_untimed_advw match_string tail (succ n) timed_match end in (* test the untimed reminders list, with advanced warnings suppressed, * for entries that match the regex *) let rec check_untimed_no_advw untimed n timed_match = match untimed with |[] -> begin match timed_match with |None -> let _ = beep () in draw_error iface "search expression not found." false; assert (doupdate ()); (iface, reminders) |Some (timed_match_ts, timed_match_iface) -> handle_selection_change timed_match_iface advw_reminders false end |urem :: tail -> begin try if urem.Remind.ur_start > selected_ts then (* If we find a match, then look for an identical string in * the list of untimed reminders with advance warning enabled *) let _ = Str.search_forward search_regex urem.Remind.ur_msg 0 in let today_untimed_advw = List.filter is_current_untimed advw_reminders.Remind.curr_untimed in check_untimed_advw urem.Remind.ur_msg today_untimed_advw 1 timed_match else raise Not_found with Not_found -> check_untimed_no_advw tail (succ n) timed_match end in (* test the timed reminders list for entries that match the regex *) let rec check_timed timed = match timed with |[] -> let today_untimed_no_advw = List.filter is_current_untimed no_advw_reminders.Remind.curr_untimed in check_untimed_no_advw today_untimed_no_advw 1 None |trem :: tail -> begin try if trem.Remind.tr_start > selected_ts then let _ = Str.search_forward search_regex trem.Remind.tr_msg 0 in let tm = Unix.localtime trem.Remind.tr_start in let (rounded_time, _) = Unix.mktime (round_time iface.zoom_level tm) in let new_iface = if !Rcfile.center_cursor then { iface with top_timestamp = rounded_time -. (time_inc iface) *. (float_of_int (iface.scr.tw_lines / 2 - 1)); top_desc = 0; left_selection = (iface.scr.tw_lines / 2) - 1; right_selection = 1; selected_side = Left } else { iface with top_timestamp = rounded_time -. (time_inc iface) *. 2.; top_desc = 0; left_selection = 2; right_selection = 1; selected_side = Left } in let today_untimed_no_advw = List.filter is_current_untimed no_advw_reminders.Remind.curr_untimed in check_untimed_no_advw today_untimed_no_advw 1 (Some (trem.Remind.tr_start, new_iface)) else raise Not_found with Not_found -> check_timed tail end in let merged_rem = Remind.merge_timed no_advw_reminders.Remind.curr_timed in check_timed (List.filter is_current_timed merged_rem) with Remind.Occurrence_not_found -> let _ = beep () in draw_error iface "search expression not found." false; (iface, reminders) (* Begin entry of a search string *) let handle_begin_search (iface : interface_state_t) reminders = let new_iface = { iface with entry_mode = Extended ExtendedSearch } in draw_error iface "search expression: " true; (new_iface, reminders) (* Find the next reminder after the current selection. * This algorithm is a dirty hack, but actually seems to work: * 1) If an untimed reminder is selected, and if it is not the last * untimed reminder in the list, then highlight the next untimed reminder. * 2) Otherwise, run find_next with a regexp that matches anything. *) let handle_next_reminder (iface : interface_state_t) reminders = if iface.selected_side = Right && iface.right_selection < iface.len_untimed - iface.top_untimed then if !Rcfile.advance_warning then begin (* Compute the list of untimed reminders currently displayed to the user *) let displayed_reminders = Remind.get_untimed_reminders_for_day reminders.Remind.curr_untimed (timestamp_of_line iface iface.left_selection) in (* Compute the same list, with advance warnings suppressed *) let displayed_reminders_no_advw = let reminders_no_advw = Remind.create_three_month ~suppress_advwarn:true (timestamp_of_line iface iface.left_selection) in Remind.get_untimed_reminders_for_day reminders_no_advw.Remind.curr_untimed (timestamp_of_line iface iface.left_selection) in (* Index of currently selected reminder within displayed_reminders *) let selection_index = iface.right_selection + iface.top_untimed in (* Simultaneously iterate through the two lists until we reach * the currently selected element. Theoretically displayed_reminders is a * superset of displayed_reminders_no_advw with ordering preserved, so we * should be able to match identical elements as we go. *) let rec iter_match superset subset n prev_iface prev_rem = match superset with | [] -> (* Some sort of search failure. Just skip over today's untimed * reminders. *) handle_find_next iface reminders (Some (Str.regexp "")) | superset_head :: superset_tail -> begin match subset with | [] -> (* Ran out of reminders in the list with advance warning * suppressed. Therefore we can skip over untimed reminders. *) handle_find_next iface reminders (Some (Str.regexp "")) | subset_head :: subset_tail -> if n > selection_index then let (next_iface, next_rem) = handle_scrolldown_untimed prev_iface prev_rem in if superset_head = subset_head then (* This should be the correct element. End here. *) (next_iface, next_rem) else (* Keep searching forward through superset list * to try to locate this element. *) iter_match superset_tail subset (succ n) next_iface next_rem else if superset_head = subset_head then begin (* Iterate both... *) iter_match superset_tail subset_tail (succ n) prev_iface prev_rem end else begin (* Iterate superset only *) iter_match superset_tail subset (succ n) prev_iface prev_rem end end in iter_match displayed_reminders displayed_reminders_no_advw 1 iface reminders end else (* Easy case. If the user has not selected advance warning, we can just * scroll down the untimed reminders window. *) handle_scrolldown_untimed iface reminders else handle_find_next iface reminders (Some (Str.regexp "")) (* View the reminders for the selected date using 'less'. * If 'trigger_all' is true, then all nonexpired reminders are * triggered. *) let handle_view_reminders (iface : interface_state_t) reminders trigger_all = let ts = timestamp_of_line iface iface.left_selection in let tm = Unix.localtime ts in let rem_date_str = (Utility.string_of_tm_mon tm.Unix.tm_mon) ^ " " ^ (string_of_int tm.Unix.tm_mday) ^ " " ^ (string_of_int (tm.Unix.tm_year + 1900)) in let partial_command = if trigger_all then !Rcfile.remind_command ^ " -q -g -t " else !Rcfile.remind_command ^ " -q -g " in let command = partial_command ^ !Rcfile.reminders_file ^ " " ^ rem_date_str ^ " | less -c" in def_prog_mode (); endwin (); let _ = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; handle_refresh iface reminders (* View Remind's formatted calendar output for the selected date. If * 'week_only' is true, then create a week calendar, otherwise a month * calendar. *) let handle_view_calendar (iface : interface_state_t) reminders week_only = let ts = timestamp_of_line iface iface.left_selection in let tm = Unix.localtime ts in let rem_date_str = (Utility.string_of_tm_mon tm.Unix.tm_mon) ^ " " ^ (string_of_int tm.Unix.tm_mday) ^ " " ^ (string_of_int (tm.Unix.tm_year + 1900)) in let partial_command = if week_only then Printf.sprintf "%s -c+1 -w%d " !Rcfile.remind_command iface.scr.cols else Printf.sprintf "%s -c -w%d " !Rcfile.remind_command iface.scr.cols in let time_option = if !Rcfile.description_12_hour then "-b0 " else "-b1 " in let weekday_option = if !Rcfile.week_starts_monday then "-m " else "" in let command = partial_command ^ time_option ^ weekday_option ^ !Rcfile.reminders_file ^ " " ^ rem_date_str ^ " | less -c" in def_prog_mode (); endwin (); let _ = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; handle_refresh iface reminders let handle_view_keybindings (iface : interface_state_t) reminders = let bindings = ref [] in let find_binding commandstr operation = match operation with |Rcfile.CommandOp command -> begin try let key_str = Hashtbl.find Rcfile.table_command_key command in bindings := (Printf.sprintf "%-30s%-20s\n" commandstr key_str) :: !bindings with Not_found -> bindings := (Printf.sprintf "%-30s\n" commandstr) :: !bindings end |Rcfile.EntryOp entry -> begin try let key_str = Hashtbl.find Rcfile.table_entry_key entry in bindings := (Printf.sprintf "%-30s%-20s\n" commandstr key_str) :: !bindings with Not_found -> bindings := (Printf.sprintf "%-30s\n" commandstr) :: !bindings end in Hashtbl.iter find_binding Rcfile.table_commandstr_command; let sorted_list = List.fast_sort Pervasives.compare !bindings in def_prog_mode (); endwin (); let out_channel = Unix.open_process_out "less" in List.iter (output_string out_channel) sorted_list; flush out_channel; let _ = Unix.close_process_out out_channel in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; handle_refresh iface reminders (* Handle scrolling down during selection dialog loop *) let handle_selection_dialog_scrolldown (elements : string list) (selection : int) (top : int) = if selection < pred (List.length elements) then let lines, cols = get_size () in let new_selection = succ selection in let new_top = if new_selection - top >= pred lines then succ top else top in (new_selection, new_top) else (selection, top) (* Handle scrolling up during selection dialog loop *) let handle_selection_dialog_scrollup (elements : string list) (selection : int) (top : int) = if selection > 0 then let new_selection = pred selection in let new_top = if new_selection < top then pred top else top in (new_selection, new_top) else (selection, top) (* Begin a selection dialog loop *) let do_selection_dialog (iface : interface_state_t) (title : string) (elements : string list) = let init_selection = 0 and init_top = 0 in let rec selection_loop (selection, top) = draw_selection_dialog iface title elements selection top; let key = wgetch iface.scr.help_win in (* trap the wgetch timeout *) if key <> ~-1 then try match Rcfile.command_of_key key with |Rcfile.ScrollDown -> selection_loop (handle_selection_dialog_scrolldown elements selection top) |Rcfile.ScrollUp -> selection_loop (handle_selection_dialog_scrollup elements selection top) |Rcfile.Edit -> List.nth elements selection |_ -> let _ = beep () in selection_loop (selection, top) with Not_found -> let _ = beep () in selection_loop (selection, top) else selection_loop (selection, top) in selection_loop (init_selection, init_top) (* handle editing the selected reminder *) let handle_edit (iface : interface_state_t) reminders = let adjust_s len s = let pad = s ^ (String.make len ' ') in Utility.utf8_string_before pad len in let fl = match iface.selected_side with |Left -> begin match iface.timed_lineinfo.(iface.left_selection) with | [] -> None | tline :: [] -> Some (tline.tl_filename, tline.tl_linenum, tline.tl_msg) | rem_list -> let sorted_rem_list = List.fast_sort sort_lineinfo rem_list in let get_msg tline = (adjust_s 16 tline.tl_timestr) ^ tline.tl_msg in let msg_list = List.rev_map get_msg sorted_rem_list in let selected_msg = do_selection_dialog iface "Choose a reminder to edit" msg_list in let test_msg_match tline = ((adjust_s 16 tline.tl_timestr) ^ tline.tl_msg) = selected_msg in let tline = (List.find test_msg_match sorted_rem_list) in Some (tline.tl_filename, tline.tl_linenum, tline.tl_msg) end |Right -> begin match iface.untimed_lineinfo.(iface.right_selection) with | Some uline -> Some (uline.ul_filename, uline.ul_linenum, uline.ul_msg) | None -> None end in begin match fl with |None -> if iface.selected_side = Left then handle_new_reminder iface reminders Timed (Utility.expand_file !Rcfile.reminders_file) else handle_new_reminder iface reminders Untimed (Utility.expand_file !Rcfile.reminders_file) |Some (filename, line_num, msg) -> let filename_sub = Str.regexp "%file%" in let lineno_sub = Str.regexp "%line%" in let command_partial = Str.global_replace filename_sub filename !Rcfile.edit_old_command in let command = Str.global_replace lineno_sub line_num command_partial in def_prog_mode (); endwin (); let _ = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; let r = Remind.create_three_month iface.top_timestamp in (* if the untimed list has been altered, change the focus * to the first element *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } else iface in handle_refresh new_iface r end (* handle free editing of the reminders file *) let handle_edit_any (iface : interface_state_t) reminders remfile = let filename_sub = Str.regexp "%file%" in let command = Str.global_replace filename_sub remfile !Rcfile.edit_any_command in def_prog_mode (); endwin (); let _ = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; let r = Remind.create_three_month iface.top_timestamp in (* if the untimed list has been altered, change the focus * to the first element *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } else iface in handle_refresh new_iface r (* handle scrolling the description window up *) let handle_scroll_desc_up iface reminders = let new_iface = {iface with top_desc = succ iface.top_desc} in handle_refresh new_iface reminders (* handle scrolling the description window down *) let handle_scroll_desc_down iface reminders = let top = max 0 (pred iface.top_desc) in let new_iface = {iface with top_desc = top} in handle_refresh new_iface reminders (* auxiliary function for the following *) let handle_copy_reminder_aux iface reminders copy_only = let adjust_s len s = let pad = s ^ (String.make len ' ') in Utility.utf8_string_before pad len in let fl = match iface.selected_side with |Left -> begin match iface.timed_lineinfo.(iface.left_selection) with | [] -> None | tline :: [] -> Some (tline.tl_filename, tline.tl_linenum) | rem_list -> let sorted_rem_list = List.fast_sort sort_lineinfo rem_list in let get_msg tline = (adjust_s 16 tline.tl_timestr) ^ tline.tl_msg in let msg_list = List.rev_map get_msg sorted_rem_list in let selected_msg = let dialog_msg = if copy_only then "Choose a reminder to copy" else "Choose a reminder to cut" in do_selection_dialog iface dialog_msg msg_list in let _ = handle_refresh iface reminders in let test_msg_match tline = ((adjust_s 16 tline.tl_timestr) ^ tline.tl_msg) = selected_msg in let tline = (List.find test_msg_match sorted_rem_list) in Some (tline.tl_filename, tline.tl_linenum) end |Right -> begin match iface.untimed_lineinfo.(iface.right_selection) with |Some uline -> Some (uline.ul_filename, uline.ul_linenum) |None -> None end in begin match fl with |None -> let _ = beep () in draw_error iface "no reminder is selected." false; assert (doupdate ()); (iface, fl) |Some (filename, line_num_str) -> let in_channel = open_in filename in let cont_regex = Str.regexp ".*\\(\\\\\\)$" in begin try (* grab a copy of the specified line *) let line = ref "" in for curr_line = 1 to int_of_string line_num_str do (* concatenate lines with trailing backslashes *) if Str.string_match cont_regex !line 0 then let bs_loc = Str.group_beginning 1 in line := (Str.string_before !line bs_loc) ^ (input_line in_channel) else line := input_line in_channel done; close_in in_channel; (* break the REM line up into chunks corresponding to the different fields *) let rem_kw_regex = Str.regexp ("\\(REM\\|PRIORITY\\|SKIP\\|BEFORE\\|AFTER\\|" ^ "OMIT\\|AT\\|SCHED\\|WARN\\|UNTIL\\|SCANFROM\\|DURATION\\|TAG\\|" ^ "MSG\\|MSF\\|RUN\\|CAL\\|SATISFY\\|SPECIAL\\|PS\\|PSFILE\\)") in let rem_chunks = Str.full_split rem_kw_regex !line in (* merge the chunks back together, but replace the REM and AT clauses * with special markers *) let rec merge_chunks chunks s found_rem = match chunks with | [] -> if found_rem then s else "REMREPLACE " ^ s | (Str.Delim "REM") :: (Str.Text datespec) :: tail -> merge_chunks tail (s ^ "REMREPLACE") true | (Str.Delim "REM") :: tail -> merge_chunks tail (s ^ "REMREPLACE") true | (Str.Delim "AT") :: (Str.Text timespec) :: tail -> merge_chunks tail (s ^ "ATREPLACE") found_rem | (Str.Delim "AT") :: tail -> merge_chunks tail (s ^ "ATREPLACE") found_rem | (Str.Delim x) :: tail -> merge_chunks tail (s ^ x) found_rem | (Str.Text x) :: tail -> merge_chunks tail (s ^ x) found_rem in let marked_remline = merge_chunks rem_chunks "" false in let new_iface = {iface with rem_buffer = marked_remline} in if copy_only then begin draw_error iface "copied reminder to clipboard." false; assert (doupdate ()); end else (); (new_iface, fl) with |End_of_file -> close_in in_channel; let _ = beep () in draw_error iface "error while copying reminder." false; assert (doupdate ()); (iface, fl) |_ -> let _ = beep () in draw_error iface "unable to parse selected reminder." false; assert (doupdate ()); (iface, fl) end end (* handle copying a reminder string to the buffer *) let handle_copy_reminder iface reminders copy_only = let new_iface, _ = handle_copy_reminder_aux iface reminders copy_only in (new_iface, reminders) (* handle pasting a reminder into a new location *) let handle_paste_reminder (iface : interface_state_t) reminders remfile = let ts = timestamp_of_line iface iface.left_selection in let tm = Unix.localtime ts in let rem_datespec = "REM " ^ Utility.string_of_tm_mon tm.Unix.tm_mon ^ " " ^ string_of_int tm.Unix.tm_mday ^ " " ^ string_of_int (tm.Unix.tm_year + 1900) ^ " " and at_timespec = "AT " ^ Printf.sprintf "%.2d" tm.Unix.tm_hour ^ ":" ^ Printf.sprintf "%.2d" tm.Unix.tm_min ^ " " in (* replace REMREPLACE and ATREPLACE keywords by sensible REM and * AT clauses corresponding to the selected date and time *) let rem_regex = Str.regexp "REMREPLACE" in let at_regex = Str.regexp "ATREPLACE" in let temp = Str.replace_first rem_regex rem_datespec iface.rem_buffer in let new_remline = Str.replace_first at_regex at_timespec temp in (* paste into the reminders file *) let remfile_channel = open_out_gen [Open_append; Open_creat; Open_text] 416 remfile in output_string remfile_channel new_remline; close_out remfile_channel; (* open reminders file in editor *) let filename_sub = Str.regexp "%file%" in let command = Str.global_replace filename_sub remfile !Rcfile.edit_new_command in def_prog_mode (); endwin (); let _ = Unix.system command in reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; let r = Remind.create_three_month iface.top_timestamp in (* if the untimed list has been altered, change the focus to * the first element of the list *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } else iface in handle_refresh new_iface r (* handle cutting a reminder and dropping it in the clipboard *) let handle_cut_reminder iface reminders = let (iface, fl) = handle_copy_reminder_aux iface reminders false in begin match fl with |None -> (iface, reminders) |Some (filename, line_num_str) -> let in_channel = open_in filename in let cont_regex = Str.regexp ".*\\(\\\\\\)$" in (* load in the file, but skip over the selected reminder *) let rec process_in_lines lines continuations line_num = try let line = input_line in_channel in if line_num = int_of_string line_num_str then (* throw out any continued lines *) process_in_lines lines [] (succ line_num) else if Str.string_match cont_regex line 0 then (* if there's a backslash, buffer the line in continuations list *) process_in_lines lines (line :: continuations) (succ line_num) else (* if there's no backslash, go ahead and dump the continuations list * into the list of lines to write *) process_in_lines (line :: (continuations @ lines)) [] (succ line_num) with End_of_file -> close_in in_channel; List.rev lines in let remaining_lines = process_in_lines [] [] 1 in let out_channel = open_out filename in (* write out the new file *) let rec write_lines lines = begin match lines with | [] -> close_out out_channel | line :: tail -> output_string out_channel (line ^ "\n"); write_lines tail end in write_lines remaining_lines; let r = Remind.create_three_month iface.top_timestamp in (* if the untimed list has been altered, change the focus to * the first element of the list *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { iface with top_untimed = 0; top_desc = 0; right_selection = 1 } else iface in let final_iface, _ = handle_refresh new_iface r in draw_error final_iface "cut reminder to clipboard." false; assert (doupdate ()); (final_iface, r) end (* handle jumping to a specified date *) let handle_goto (iface : interface_state_t) reminders = let tm = Unix.localtime (Unix.time () -. (time_inc iface)) in let len = String.length iface.extended_input in if not (List.mem len [2; 4; 8]) then failwith "length must be 2, 4, or 8 characters." else begin let (year_s, month_s, day_s) = if !Rcfile.goto_big_endian then if len = 8 then ( String.sub iface.extended_input 0 4, String.sub iface.extended_input 4 2, String.sub iface.extended_input 6 2 ) else if len = 4 then ( string_of_int (tm.Unix.tm_year + 1900), String.sub iface.extended_input 0 2, String.sub iface.extended_input 2 2 ) else ( string_of_int (tm.Unix.tm_year + 1900), string_of_int (tm.Unix.tm_mon + 1), iface.extended_input ) else if len = 8 then ( String.sub iface.extended_input 4 4, String.sub iface.extended_input 2 2, String.sub iface.extended_input 0 2 ) else if len = 4 then ( string_of_int (tm.Unix.tm_year + 1900), String.sub iface.extended_input 2 2, String.sub iface.extended_input 0 2 ) else ( string_of_int (tm.Unix.tm_year + 1900), string_of_int (tm.Unix.tm_mon + 1), iface.extended_input ) in let year = (int_of_string year_s) - 1900 and month = (int_of_string month_s) - 1 and day = int_of_string day_s in let jump_time = { tm with Unix.tm_year = year; Unix.tm_mon = month; Unix.tm_mday = day } in let (rounded_time, rt) = try Unix.mktime (round_time iface.zoom_level jump_time) with _ -> failwith "requested date is out of range." in if (rt.Unix.tm_year + 1900) < 1991 || (rt.Unix.tm_year + 1900) > 2037 then failwith "requested year is out of range." else if rt.Unix.tm_mon <> jump_time.Unix.tm_mon then failwith "requested month is out of range." else if rt.Unix.tm_mday <> jump_time.Unix.tm_mday then failwith "requested day of the month is out of range." else (); let new_iface = { iface with top_timestamp = if !Rcfile.center_cursor then rounded_time -. (time_inc iface) *. (float_of_int ((iface.scr.tw_lines / 2) - 2)) else rounded_time -. (time_inc iface) *. 1.; top_desc = 0; selected_side = Left; left_selection = if !Rcfile.center_cursor then (iface.scr.tw_lines / 2) - 1 else 2; right_selection = 1; entry_mode = Normal; extended_input = "" } in handle_selection_change new_iface reminders false end (* Begin entry of a date/time to navigate to *) let handle_begin_goto (iface : interface_state_t) reminders = let new_iface = { iface with entry_mode = Extended ExtendedGoto } in if !Rcfile.goto_big_endian then draw_error iface "go to date [[YYYY]MM]DD: " true else draw_error iface "go to date DD[MM[YYYY]]: " true; (new_iface, reminders) (* Handle creation of a quick event *) let handle_quick_event (iface : interface_state_t) reminders remfile = try let (rem_spec, remline) = append_quick_event iface.extended_input remfile in (* navigate to the new reminder *) let (is_timed, start) = match rem_spec with | Time_lang.Timed (x, _) -> (true, x) | Time_lang.Untimed x -> (false, x) in let rounded_time = let rt_shift = if is_timed then let (x, _) = Unix.mktime (round_time iface.zoom_level start) in x else let (x, _) = Unix.mktime (round_time iface.zoom_level {start with Unix.tm_hour = 8}) in x in rt_shift -. (time_inc iface) in let r = Remind.create_three_month iface.top_timestamp in let new_iface = { iface with top_timestamp = if !Rcfile.center_cursor then rounded_time -. (time_inc iface) *. (float_of_int ((iface.scr.tw_lines / 2) - 2)) else rounded_time -. (time_inc iface) *. 1.; top_desc = 0; selected_side = if is_timed then Left else Right; left_selection = if !Rcfile.center_cursor then (iface.scr.tw_lines / 2) - 1 else 2; right_selection = 1; entry_mode = Normal; extended_input = "" } in handle_selection_change new_iface r false with Time_lang.Event_parse_error s -> failwith s (* Begin entry of a quick event *) let handle_begin_quick_event (iface : interface_state_t) reminders = let new_iface = { iface with entry_mode = Extended ExtendedQuick } in draw_error iface "event description: " true; (new_iface, reminders) (* handle keyboard input for a hotkey, and update the display appropriately *) let handle_keypress_normal key (iface : interface_state_t) reminders = try match Rcfile.command_of_key key with |Rcfile.ScrollDown -> begin match iface.selected_side with |Left -> handle_scrolldown_timed iface reminders |Right -> handle_scrolldown_untimed iface reminders end |Rcfile.ScrollUp -> begin match iface.selected_side with |Left -> handle_scrollup_timed iface reminders |Right -> handle_scrollup_untimed iface reminders end |Rcfile.NextDay -> let jump_func day = {day with Unix.tm_mday = succ day.Unix.tm_mday} in handle_jump iface reminders jump_func |Rcfile.PrevDay -> let jump_func day = {day with Unix.tm_mday = pred day.Unix.tm_mday} in handle_jump iface reminders jump_func |Rcfile.NextWeek -> let jump_func day = {day with Unix.tm_mday = day.Unix.tm_mday + 7} in handle_jump iface reminders jump_func |Rcfile.PrevWeek -> let jump_func day = {day with Unix.tm_mday = day.Unix.tm_mday - 7} in handle_jump iface reminders jump_func |Rcfile.NextMonth -> let jump_func day = {day with Unix.tm_mon = succ day.Unix.tm_mon} in handle_jump iface reminders jump_func |Rcfile.PrevMonth -> let jump_func day = {day with Unix.tm_mon = pred day.Unix.tm_mon} in handle_jump iface reminders jump_func |Rcfile.Zoom -> handle_zoom iface reminders |Rcfile.SwitchWindow -> handle_switch_focus iface reminders |Rcfile.Home -> handle_home iface reminders |Rcfile.Goto -> handle_begin_goto iface reminders |Rcfile.Edit -> handle_edit iface reminders |Rcfile.EditAny -> let all_remfiles = Remind.get_included_remfiles () in let selected_remfile = (* if there's only one remfile, jump right in, otherwise * pop up a selection dialog *) if List.length all_remfiles > 1 then do_selection_dialog iface "Choose a reminders file to edit" all_remfiles else List.hd all_remfiles in handle_edit_any iface reminders selected_remfile |Rcfile.CopyReminder -> handle_copy_reminder iface reminders true |Rcfile.CutReminder -> handle_cut_reminder iface reminders |Rcfile.PasteReminder -> if iface.rem_buffer = "" then begin let _ = beep () in draw_error iface "clipboard is empty." false; assert (doupdate ()); (iface, reminders) end else begin handle_paste_reminder iface reminders (Utility.expand_file !Rcfile.reminders_file) end |Rcfile.PasteReminderDialog -> if iface.rem_buffer = "" then begin let _ = beep () in draw_error iface "clipboard is empty." false; assert (doupdate ()); (iface, reminders) end else begin let all_remfiles = Remind.get_included_remfiles () in let selected_remfile = (* if there's only one remfile, jump right in, otherwise * pop up a selection dialog *) if List.length all_remfiles > 1 then do_selection_dialog iface "Choose a reminders file to paste into" all_remfiles else List.hd all_remfiles in handle_paste_reminder iface reminders selected_remfile end |Rcfile.ScrollDescUp -> handle_scroll_desc_up iface reminders |Rcfile.ScrollDescDown -> handle_scroll_desc_down iface reminders |Rcfile.QuickEvent -> handle_begin_quick_event iface reminders |Rcfile.NewTimed -> handle_new_reminder iface reminders Timed (Utility.expand_file !Rcfile.reminders_file) |Rcfile.NewTimedDialog -> let remfile = do_selection_dialog iface "Choose a reminders file" (Remind.get_included_remfiles ()) in handle_new_reminder iface reminders Timed remfile |Rcfile.NewUntimed -> handle_new_reminder iface reminders Untimed (Utility.expand_file !Rcfile.reminders_file) |Rcfile.NewUntimedDialog -> let remfile = do_selection_dialog iface "Choose a reminders file" (Remind.get_included_remfiles ()) in handle_new_reminder iface reminders Untimed remfile |Rcfile.NewGenReminder x -> handle_new_reminder iface reminders (General x) (Utility.expand_file !Rcfile.reminders_file) |Rcfile.NewGenReminderDialog x -> let remfile = do_selection_dialog iface "Choose a reminders file" (Remind.get_included_remfiles ()) in handle_new_reminder iface reminders (General x) remfile |Rcfile.SearchNext -> handle_find_next iface reminders None |Rcfile.BeginSearch -> handle_begin_search iface reminders |Rcfile.NextReminder -> handle_next_reminder iface reminders |Rcfile.ViewReminders -> handle_view_reminders iface reminders false |Rcfile.ViewAllReminders -> handle_view_reminders iface reminders true |Rcfile.ViewWeek -> handle_view_calendar iface reminders true |Rcfile.ViewMonth -> handle_view_calendar iface reminders false |Rcfile.ViewKeybindings -> handle_view_keybindings iface reminders |Rcfile.Refresh -> (* NOTE: I'm not sure why the endwin call is necessary here, * but I'm having problems getting a true full-screen refresh * without it. *) def_prog_mode (); endwin (); reset_prog_mode (); begin try assert (curs_set 0) with _ -> () end; let i = draw_msg iface in handle_refresh i reminders |Rcfile.Quit -> let new_iface = {iface with run_wyrd = false} in (new_iface, reminders) with Not_found -> let _ = beep () in draw_error iface "key is not bound." false; assert (doupdate ()); (iface, reminders) (* handle keyboard input and update the display appropriately *) let handle_keypress key (iface : interface_state_t) reminders = match iface.entry_mode with |Normal -> handle_keypress_normal key (iface : interface_state_t) reminders |Extended ext_mode -> begin try begin match Rcfile.entry_of_key key with |Rcfile.EntryComplete -> begin match ext_mode with |ExtendedSearch -> begin try let new_iface = { iface with search_regex = Str.regexp_case_fold iface.extended_input; extended_input = ""; entry_mode = Normal } in handle_find_next new_iface reminders None with Failure err -> let new_iface = { iface with extended_input = ""; entry_mode = Normal } in let _ = beep () in draw_error new_iface ("syntax error in search string: " ^ err) false; assert (doupdate ()); (new_iface, reminders) end |ExtendedGoto -> begin try handle_goto iface reminders with Failure err -> let new_iface = { iface with extended_input = ""; entry_mode = Normal } in let _ = beep () in draw_error new_iface ("syntax error in date specifier: " ^ err) false; assert (doupdate ()); (new_iface, reminders) end |ExtendedQuick -> begin try handle_quick_event iface reminders (Utility.expand_file !Rcfile.reminders_file) with Failure err -> let new_iface = { iface with extended_input = ""; entry_mode = Normal } in let _ = beep () in draw_error new_iface ("syntax error in event description: " ^ err) false; assert (doupdate ()); (new_iface, reminders) end end |Rcfile.EntryBackspace -> let len = Utility.utf8_len iface.extended_input in if len > 0 then begin let new_iface = { iface with extended_input = Utility.utf8_string_before iface.extended_input (pred len) } in let prompt = match ext_mode with |ExtendedSearch -> "search expression: " |ExtendedGoto -> if !Rcfile.goto_big_endian then "go to date [[YYYY]MM]DD: " else "go to date DD[MM[YYYY]]: " |ExtendedQuick -> "event description: " in draw_error iface (prompt ^ new_iface.extended_input) true; (new_iface, reminders) end else let _ = beep () in (iface, reminders) |Rcfile.EntryExit -> let new_iface = { iface with extended_input = ""; entry_mode = Normal } in let msg = match ext_mode with |ExtendedSearch -> "search cancelled." |ExtendedGoto -> "date entry cancelled." |ExtendedQuick -> "quick event cancelled." in draw_error new_iface msg false; (new_iface, reminders) end with Not_found -> begin match ext_mode with |ExtendedGoto -> begin try (* only digits are accepted for goto dates *) if key >= 48 && key <= 57 && (String.length iface.extended_input < 8) then begin let c = char_of_int key in let new_iface = { iface with extended_input = iface.extended_input ^ (String.make 1 c) } in if !Rcfile.goto_big_endian then draw_error iface ("go to date [[YYYY]MM]DD: " ^ new_iface.extended_input) true else draw_error iface ("go to date DD[MM[YYYY]]: " ^ new_iface.extended_input) true; (new_iface, reminders) end else failwith "date characters must be digits" with Failure _ -> let _ = beep () in (iface, reminders) end |_ -> begin try (* only printable characters are accepted for search strings and quick events *) if key >= 32 && key <= 126 then begin let c = char_of_int key in let new_iface = { iface with extended_input = iface.extended_input ^ (String.make 1 c) } in let prompt = match ext_mode with |ExtendedSearch -> "search expression: " |ExtendedQuick -> "event description: " |_ -> failwith "logical error in generating extended entry string" in draw_error new_iface (prompt ^ new_iface.extended_input) true; (new_iface, reminders) end else let err_msg = match ext_mode with |ExtendedSearch -> "cannot search for unprintable characters" |ExtendedQuick -> "events cannot contain unprintable characters" |ExtendedGoto -> "logical error in generating extended entry string" in failwith err_msg with Failure _ -> let _ = beep () in (iface, reminders) end end end let rec do_main_loop (iface : interface_state_t) reminders last_update = if iface.run_wyrd then begin if String.length reminders.Remind.remind_error > 0 then draw_error iface ("Error in reminders file: \"" ^ reminders.Remind.remind_error ^ "\"") false else (); (* refresh the msg window (which contains a clock) * every wgetch timeout cycle *) let iface = draw_msg iface in begin match iface.resize_failed_win with | None -> assert (doupdate ()) | Some w -> () end; let key = wgetch iface.scr.help_win in let new_iface, new_reminders = (* key = -1 is ncurses wgetch timeout error *) if key <> ~- 1 then if key = Key.resize then handle_resize iface reminders else begin match iface.resize_failed_win with | None -> handle_keypress key iface reminders | Some w -> let _ = beep () in (iface, reminders) end else if iface.track_home then (* cursor tracks the current time if requested *) handle_home iface reminders else (iface, reminders) in let curr_time = Unix.time () in (* poll remind(1) every 5 minutes and update display *) if curr_time -. last_update > 300.0 then begin let r = Remind.create_three_month new_iface.top_timestamp in (* if the untimed list has been altered, change the focus to * the timed window *) let new_iface = if List.length r.Remind.curr_untimed <> List.length reminders.Remind.curr_untimed then { new_iface with selected_side = Left; top_untimed = 0; right_selection = 1 } else new_iface in let (iface2, reminders2) = handle_refresh new_iface r in do_main_loop iface2 reminders2 curr_time end else do_main_loop new_iface new_reminders last_update end else endwin () (* exit main loop *) (* initialize the interface and begin the main loop *) let run (iface : interface_state_t) = let set_bkgd win obj = try let color_index = Hashtbl.find Rcfile.object_palette obj in wbkgd win ((A.color_pair color_index) lor (int_of_char ' ')) with Not_found -> () in (* set up the proper background colors for all the windows *) set_bkgd iface.scr.help_win Rcfile.Help; set_bkgd iface.scr.timed_win Rcfile.Timed_default; set_bkgd iface.scr.calendar_win Rcfile.Calendar_labels; set_bkgd iface.scr.untimed_win Rcfile.Untimed_reminder; set_bkgd iface.scr.msg_win Rcfile.Description; scrollok iface.scr.timed_win true; let reminders = Remind.create_three_month (iface.top_timestamp) in assert (keypad iface.scr.help_win true); draw_help iface; draw_date_strip iface; let new_iface = draw_timed iface reminders.Remind.all_timed in draw_calendar new_iface reminders; let new_iface = draw_untimed new_iface reminders.Remind.curr_untimed in let new_iface = draw_msg new_iface in draw_error new_iface "" false; assert (doupdate ()); do_main_loop new_iface reminders (Unix.time ()) (* arch-tag: DO_NOT_CHANGE_b4519dd2-7e94-4cbf-931a-bb5f97445cbf *) wyrd-1.4.4/prep-release.sh0000755000175000017500000000101110757447265014126 0ustar paulpaul#!/bin/bash # 'prep-release' script # Make all the last-minute changes to prepare the sources for packaging # in a release tarball # # Usage: prep-release.sh DESTDIR # echo "Exporting revision..." bzr export $1 echo "Exporting dependencies..." bzr export $1/curses $HOME/src/bzr-repo/libcurses-ocaml-dev cd $1 echo "Generating ./configure ..." autoconf && rm -rf autom4te.cache echo "Creating documentation..." cd doc && make &> /dev/null echo "Done." # arch-tag: DO_NOT_CHANGE_f08da183-17c9-42c8-904b-7d6bab8dfe50 wyrd-1.4.4/wyrdrc0000644000175000017500000001320110757447265012444 0ustar paulpaul# Wyrd run-configuration file # command for the Remind executable set remind_command="remind" # the default reminder file to display set reminders_file="$HOME/.reminders" # command for editing an old appointment, given a line number %line% and filename %file% set edit_old_command="$EDITOR +%line% %file%" # command for editing a new appointment, given a filename %file% set edit_new_command="$EDITOR +999999 %file%" # command for free editing of the reminders file, given a filename %file% set edit_any_command="$EDITOR %file%" # templates for creating new appointments # %monname% -> month name, %mon% -> month number, %mday% -> day of the month, # %year% -> year, %hour% -> hour, %min% -> minute, %wdayname% -> weekday name # %wday% -> weekday number set timed_template="REM %monname% %mday% %year% AT %hour%:%min% DURATION 1:00 MSG " set untimed_template="REM %monname% %mday% %year% MSG " # weekly recurrence set template0="REM %wdayname% AT %hour%:%min% DURATION 1:00 MSG " set template1="REM %wdayname% MSG " # monthly recurrence set template2="REM %mday% AT %hour%:%min% DURATION 1:00 MSG " set template3="REM %mday% MSG " # algorithm to use for determining busy level # "1" -> count the number of reminders in each day # "2" -> count the number of hours of reminders in each day set busy_algorithm="1" # for busy_algorithm="2", assume that untimed reminders occupy this many minutes set untimed_duration="60" # if busy_algorithm="1", number of reminders per day allowed for each calendar # colorization level; if busy_algorithm="2", use number of hours of reminders # per day set busy_level1="1" # level1 color set busy_level2="3" # level2 color set busy_level3="5" # level2 color, bold set busy_level4="7" # level3 color # (everything else is level3 color, bold) # first day of the week is Sunday set week_starts_monday="false" # 12/24 hour time settings set schedule_12_hour="false" set selection_12_hour="true" set status_12_hour="true" set description_12_hour="true" # whether or not to keep the cursor centered when scrolling through timed # reminders set center_cursor="false" # date syntax for the 'go to date' command can be big or little endian set goto_big_endian="true" # date syntax for the "quick reminder" command can be US style # (6/1 -> June 1) or non-US style (6/1 -> January 6) set quick_date_US="true" # whether or not to number weeks within the month calendar set number_weeks="false" # whether or not the cursor should follow the current time # after pressing the "home" key set home_sticky="true" # whether or not to display advance warnings set advance_warning="false" # width of the untimed reminders window set untimed_window_width="40" # whether or not to render untimed reminders in boldface set untimed_bold="true" # key bindings bind "j" scroll_down bind "" scroll_down bind "k" scroll_up bind "" scroll_up bind "h" switch_window bind "l" switch_window bind "" switch_window bind "" switch_window bind "" previous_day bind "4" previous_day bind "<" previous_day bind "H" previous_day bind "" next_day bind "6" next_day bind ">" next_day bind "L" next_day bind "8" previous_week bind "[" previous_week bind "K" previous_week bind "2" next_week bind "]" next_week bind "J" next_week bind "{" previous_month bind "}" next_month bind "" home bind "g" goto bind "z" zoom bind "" edit bind "" edit bind "e" edit_any bind "y" copy bind "X" cut bind "p" paste bind "P" paste_dialog bind "d" scroll_description_up bind "D" scroll_description_down bind "q" quick_add bind "t" new_timed bind "T" new_timed_dialog bind "u" new_untimed bind "U" new_untimed_dialog bind "w" new_template0 bind "W" new_template1 bind "m" new_template2 bind "M" new_template3 bind "n" search_next bind "/" begin_search bind "" next_reminder bind "r" view_remind bind "R" view_remind_all bind "c" view_week bind "C" view_month bind "?" help bind "\\Cl" refresh bind "Q" quit bind "" entry_complete bind "" entry_complete bind "" entry_backspace bind "" entry_cancel # set up the colors color help green blue color timed_default white black color timed_current white red color timed_reminder1 yellow blue color timed_reminder2 white red color timed_reminder3 white green color timed_reminder4 yellow magenta color untimed_reminder white black color timed_date cyan black color selection_info green blue color description white black color status green blue color calendar_labels white black color calendar_level1 white black color calendar_level2 blue black color calendar_level3 magenta black color calendar_today white red color left_divider cyan blue color right_divider cyan blue # arch-tag: DO_NOT_CHANGE_ee9bb855-2fde-4a61-8645-8ba31b35eaab wyrd-1.4.4/interface_draw.ml0000644000175000017500000010610310757447265014522 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* interface_draw.ml * All drawing operations are found here. *) open Interface open Curses open Remind open Utility (* sort timed lineinfo entries by starting timestamp *) let sort_lineinfo line1 line2 = ~- (Pervasives.compare line1.tl_start line2.tl_start) (* Word-wrap a string--split the string at whitespace boundaries * to form a list of strings, each of which has length less than * 'len'. *) let word_wrap (s : string) (len : int) = let ws = Str.regexp "[\t ]+" in let split_words = Str.split ws s in let rec process_words words lines = match words with |[] -> List.rev lines |word :: remaining_words -> let word_len = utf8_len word in begin match lines with |[] -> process_words words [""] |line :: remaining_lines -> let line_len = utf8_len line in if word_len + line_len + 1 <= len then if line_len = 0 then process_words remaining_words (word :: remaining_lines) else process_words remaining_words ((line ^ " " ^ word) :: remaining_lines) else if word_len <= len then process_words remaining_words (word :: line :: remaining_lines) else (* No choice but to break the word apart *) let front = utf8_string_before word len and back = utf8_string_after word len in process_words (back :: remaining_words) (front :: line :: remaining_lines) end in process_words split_words [] (* Generate a 12-hour clock representation of a time record *) let twelve_hour_string tm = if tm.Unix.tm_hour >= 12 then let hour = tm.Unix.tm_hour - 12 in if hour = 0 then Printf.sprintf "12:%.2dpm" tm.Unix.tm_min else Printf.sprintf "%d:%.2dpm" hour tm.Unix.tm_min else if tm.Unix.tm_hour = 0 then Printf.sprintf "12:%.2dam" tm.Unix.tm_min else Printf.sprintf "%d:%.2dam" tm.Unix.tm_hour tm.Unix.tm_min (* Generate a 12-hour clock representation of a time record, with whitespace padding *) let twelve_hour_string_pad tm = if tm.Unix.tm_hour >= 12 then let hour = tm.Unix.tm_hour - 12 in if hour = 0 then Printf.sprintf "12:%.2dpm" tm.Unix.tm_min else Printf.sprintf "%2d:%.2dpm" hour tm.Unix.tm_min else if tm.Unix.tm_hour = 0 then Printf.sprintf "12:%.2dam" tm.Unix.tm_min else Printf.sprintf "%2d:%.2dam" tm.Unix.tm_hour tm.Unix.tm_min (* Generate a 24-hour clock representation of a time record *) let twentyfour_hour_string tm = Printf.sprintf "%.2d:%.2d" tm.Unix.tm_hour tm.Unix.tm_min (* Draw a string in a specified window and location, using exactly 'len' * characters and truncating with ellipses if necessary. *) let trunc_mvwaddstr win line col len s = let fixed_s = let s_len = utf8_len s in if s_len <= len then let pad = String.make (len - s_len) ' ' in s ^ pad else if len >= 3 then (utf8_string_before s (len - 3)) ^ "..." else if len >= 0 then utf8_string_before s len else "" in assert (mvwaddstr win line col fixed_s) (* Draw the one-line help window at the top of the screen *) let draw_help (iface : interface_state_t) = Rcfile.color_on iface.scr.help_win Rcfile.Help; wattron iface.scr.help_win (A.bold lor A.underline); let rec build_help_line operations s = match operations with |[] -> s |(op, op_string) :: tail -> try let key_string = Rcfile.key_of_command op in build_help_line tail (s ^ key_string ^ ":" ^ op_string ^ " ") with Not_found -> build_help_line tail s in let help_string = build_help_line [(Rcfile.ViewKeybindings, "help"); (Rcfile.NewTimed, "new timed"); (Rcfile.NewUntimed, "new untimed"); (Rcfile.Edit, "edit"); (Rcfile.Home, "home"); (Rcfile.Zoom, "zoom"); (Rcfile.BeginSearch, "search"); (Rcfile.Quit, "quit")] "" in trunc_mvwaddstr iface.scr.help_win 0 0 iface.scr.hw_cols help_string; assert (wnoutrefresh iface.scr.help_win) (* Draw the vertical date strip at the left of the timed window. * Note: non-trivial. * The first date stamp is a special case; it is drawn at the top * of the screen and truncated at the beginning to fit before the * first date change. The remaining date stamps are all drawn immediately * after any date changes, and truncated at the end to fit in the * window. * Step 1: determine the line numbers on which the dates change * Step 2: create a string to represent the vertical strip * Step 3: draw each of the characters of the string onto the window *) let draw_date_strip (iface : interface_state_t) = (* draw the vertical line to the right of the date string *) let acs = get_acs_codes () in Rcfile.color_on iface.scr.timed_win Rcfile.Left_divider; wattron iface.scr.timed_win A.bold; mvwvline iface.scr.timed_win 0 1 acs.Acs.vline iface.scr.tw_lines; Rcfile.color_off iface.scr.timed_win Rcfile.Left_divider; (* determine the line numbers and timestamps of any date changes within the * timed window *) let rec check_timestamp date_changes timestamp line = if line >= iface.scr.tw_lines then date_changes else let timestamp_tm = Unix.localtime timestamp in let next_timestamp = timestamp +. (time_inc iface) in let temp = { timestamp_tm with Unix.tm_sec = 0; Unix.tm_min = ~- (time_inc_min iface); Unix.tm_hour = 0 } in let (_, before_midnight) = Unix.mktime temp in if timestamp_tm.Unix.tm_min = before_midnight.Unix.tm_min && timestamp_tm.Unix.tm_hour = before_midnight.Unix.tm_hour then check_timestamp ((line, timestamp) :: date_changes) next_timestamp (succ line) else check_timestamp date_changes next_timestamp (succ line) in let date_changes = List.rev (check_timestamp [] iface.top_timestamp 0) in (* generate a string to represent the vertical strip *) let date_chars = if List.length date_changes > 0 then begin (* special case for the top date string, which is always at the * top of the screen *) let (line, timestamp) = List.hd date_changes in let tm = Unix.localtime timestamp in let top_date_str = if line >= 7 then (* the date will fit completely *) (Printf.sprintf " %s %.2d" (string_of_tm_mon tm.Unix.tm_mon) tm.Unix.tm_mday) ^ (String.make (line - 7) ' ') else (* there's not enough room for the date, so truncate it *) Str.last_chars (Printf.sprintf " %s %.2d" (string_of_tm_mon tm.Unix.tm_mon) tm.Unix.tm_mday) line in (* all other dates are just rendered at the top of their respective windows *) let rec add_date date_str changes = match changes with | [] -> date_str | (line, timestamp) :: tail -> let tm = Unix.localtime timestamp in let temp = { tm with Unix.tm_mday = succ tm.Unix.tm_mday } in let (_, next_day) = Unix.mktime temp in let s_len = if List.length tail > 0 then let (next_line, _) = List.hd tail in next_line - line else iface.scr.tw_lines - line in let temp_s = (Printf.sprintf "-%s %.2d" (string_of_tm_mon next_day.Unix.tm_mon) next_day.Unix.tm_mday) ^ (String.make 100 ' ') in add_date (date_str ^ (Str.string_before temp_s s_len)) tail in add_date top_date_str date_changes end else (* if there are no date changes (e.g. for small window) then just grab the proper * date from the top_timestamp *) let tm = Unix.localtime iface.top_timestamp in (Printf.sprintf " %s %.2d" (string_of_tm_mon tm.Unix.tm_mon) tm.Unix.tm_mday) ^ (String.make (iface.scr.tw_lines - 6) ' ') in (* draw the date string vertically, one character at a time *) for i = 0 to pred iface.scr.tw_lines do if date_chars.[i] = '-' then begin wattron iface.scr.timed_win A.underline; Rcfile.color_on iface.scr.timed_win Rcfile.Timed_date; assert (mvwaddch iface.scr.timed_win i 0 acs.Acs.hline); Rcfile.color_off iface.scr.timed_win Rcfile.Timed_date; Rcfile.color_on iface.scr.timed_win Rcfile.Left_divider; assert (mvwaddch iface.scr.timed_win i 1 acs.Acs.rtee); Rcfile.color_off iface.scr.timed_win Rcfile.Left_divider; wattroff iface.scr.timed_win A.underline; end else begin Rcfile.color_on iface.scr.timed_win Rcfile.Timed_date; assert (mvwaddch iface.scr.timed_win i 0 (int_of_char date_chars.[i])); Rcfile.color_off iface.scr.timed_win Rcfile.Timed_date; end done; wattroff iface.scr.timed_win (A.bold lor A.underline); assert (wnoutrefresh iface.scr.timed_win) (* Draw a portion of the timed schedule. The algorithm iterates across all * reminders in a three month period, and draws them in one by one. An array * is used to keep track of which lines have not yet been drawn, so that these * can be filled in later. * * This routine also updates iface.timed_lineinfo. *) let draw_timed_window iface reminders top lines = let round_down x = if x >= 0.0 then int_of_float x else pred (int_of_float x) in let indent_colors = [| Rcfile.Timed_reminder1; Rcfile.Timed_reminder2; Rcfile.Timed_reminder3; Rcfile.Timed_reminder4 |] in let acs = get_acs_codes () in let blank = String.make iface.scr.tw_cols ' ' in let top_timestamp = timestamp_of_line iface top in let top_tm = Unix.localtime top_timestamp in let temp = { top_tm with Unix.tm_sec = 0; Unix.tm_min = ~- (time_inc_min iface); Unix.tm_hour = 0 } in let (_, before_midnight) = Unix.mktime temp in let string_of_tm = if !Rcfile.schedule_12_hour then twelve_hour_string_pad else twentyfour_hour_string in (* this ensures that if there are multiple reminder descriptions * displayed simultaneously, the dashes between start and end times * will line up properly *) let (desc_string_of_tm1, desc_string_of_tm2) = if !Rcfile.description_12_hour then (twelve_hour_string_pad, twelve_hour_string) else (twentyfour_hour_string, twentyfour_hour_string) in Rcfile.color_on iface.scr.timed_win Rcfile.Timed_default; (* draw in the blank timeslots *) for i = top to pred (top + lines) do iface.timed_lineinfo.(i) <- []; if i = iface.left_selection && iface.selected_side = Left then wattron iface.scr.timed_win A.reverse else wattroff iface.scr.timed_win A.reverse; let ts = timestamp_of_line iface i in let tm = Unix.localtime ts in let ts_str = string_of_tm tm in let curr_ts = Unix.time () in (* the current time is highlighted *) if curr_ts >= ts && curr_ts < (timestamp_of_line iface (succ i)) then begin Rcfile.color_on iface.scr.timed_win Rcfile.Timed_current; wattron iface.scr.timed_win A.bold end else (); if tm.Unix.tm_hour = before_midnight.Unix.tm_hour && tm.Unix.tm_min = before_midnight.Unix.tm_min then wattron iface.scr.timed_win A.underline else wattroff iface.scr.timed_win A.underline; assert (mvwaddstr iface.scr.timed_win i 2 ts_str); Rcfile.color_off iface.scr.timed_win Rcfile.Timed_current; wattroff iface.scr.timed_win A.bold; Rcfile.color_on iface.scr.timed_win Rcfile.Timed_default; let s = Str.string_before blank (iface.scr.tw_cols - 7) in assert (mvwaddstr iface.scr.timed_win i 7 s) done; Rcfile.color_off iface.scr.timed_win Rcfile.Timed_default; wattroff iface.scr.timed_win (A.reverse lor A.underline); (* draw in the timed reminders *) let rec process_reminders rem_list indent = Rcfile.color_on iface.scr.timed_win indent_colors.(indent); wattron iface.scr.timed_win A.bold; begin match rem_list with |[] -> () |rem :: tail -> let rem_top_line = round_down ((rem.tr_start -. iface.top_timestamp) /. (time_inc iface)) in let get_time_str () = if rem.tr_end > rem.tr_start then (desc_string_of_tm1 (Unix.localtime rem.tr_start)) ^ "-" ^ (desc_string_of_tm2 (Unix.localtime rem.tr_end)) ^ " " else (desc_string_of_tm1 (Unix.localtime rem.tr_start)) ^ " " in (* draw the top line of a reminder *) let clock_pad = if !Rcfile.schedule_12_hour then 10 else 8 in if rem_top_line >= top && rem_top_line < top + lines then begin let time_str = get_time_str () in let ts = timestamp_of_line iface rem_top_line in let tm = Unix.localtime ts in if rem_top_line = iface.left_selection && iface.selected_side = Left then wattron iface.scr.timed_win A.reverse else wattroff iface.scr.timed_win A.reverse; if tm.Unix.tm_hour = before_midnight.Unix.tm_hour && tm.Unix.tm_min = before_midnight.Unix.tm_min then wattron iface.scr.timed_win A.underline else wattroff iface.scr.timed_win A.underline; let curr_lineinfo = { tl_filename = rem.tr_filename; tl_linenum = rem.tr_linenum; tl_timestr = time_str; tl_msg = rem.tr_msg; tl_start = rem.tr_start } in iface.timed_lineinfo.(rem_top_line) <- (curr_lineinfo :: iface.timed_lineinfo.(rem_top_line)); trunc_mvwaddstr iface.scr.timed_win rem_top_line (clock_pad + (9 * indent)) (iface.scr.tw_cols - clock_pad - (9 * indent)) (" " ^ rem.tr_msg); assert (mvwaddch iface.scr.timed_win rem_top_line (clock_pad + (9 * indent)) acs.Acs.vline) end else (); (* draw any remaining lines of this reminder, as determined by the duration *) let count = ref 1 in while ((timestamp_of_line iface (rem_top_line + !count)) < rem.tr_end) && (rem_top_line + !count < top + lines) do if rem_top_line + !count >= top then begin let time_str = get_time_str () in let ts = timestamp_of_line iface (rem_top_line + !count) in let tm = Unix.localtime ts in if rem_top_line + !count = iface.left_selection && iface.selected_side = Left then wattron iface.scr.timed_win A.reverse else wattroff iface.scr.timed_win A.reverse; if tm.Unix.tm_hour = before_midnight.Unix.tm_hour && tm.Unix.tm_min = before_midnight.Unix.tm_min then wattron iface.scr.timed_win A.underline else wattroff iface.scr.timed_win A.underline; let curr_lineinfo = { tl_filename = rem.tr_filename; tl_linenum = rem.tr_linenum; tl_timestr = time_str; tl_msg = rem.tr_msg; tl_start = rem.tr_start } in iface.timed_lineinfo.(rem_top_line + !count) <- (curr_lineinfo :: iface.timed_lineinfo.(rem_top_line + !count)); trunc_mvwaddstr iface.scr.timed_win (rem_top_line + !count) (clock_pad + (9 * indent)) (iface.scr.tw_cols - clock_pad - (9 * indent)) " "; assert (mvwaddch iface.scr.timed_win (rem_top_line + !count) (clock_pad + (9 * indent)) acs.Acs.vline) end else (); count := succ !count done; (* The reminders list is sorted chronologically, so once we hit a reminder * that falls after the end of the calendar window we can stop. *) if rem_top_line < top + lines then process_reminders tail indent else () end; Rcfile.color_off iface.scr.timed_win indent_colors.(indent) in (* reminders are rendered in order of indentation level, so the reminders with * higher indentation overlap those with lower indentation *) for indent = 0 to pred (Array.length reminders) do process_reminders reminders.(indent) indent done; wattroff iface.scr.timed_win (A.bold lor A.reverse); assert (wnoutrefresh iface.scr.timed_win) (* Draw the entire timed reminders window *) let draw_timed iface reminders = draw_timed_window iface reminders 0 iface.scr.tw_lines; {iface with last_timed_refresh = Unix.time ()} (* Draw just a portion of the timed window when possible. If * iface.last_timed_refresh indicates that the display is stale, * then do a whole-window update. This is to make sure that the * current timeslot gets highlighted properly, and old highlights * get erased. *) let draw_timed_try_window iface reminders top lines = let curr_tm = Unix.localtime (Unix.time ()) in let timeslot = round_time iface.zoom_level curr_tm in let (ts, _) = Unix.mktime timeslot in if iface.last_timed_refresh < ts then draw_timed iface reminders else begin draw_timed_window iface reminders top lines; iface end (* render a calendar for the given reminders record *) let draw_calendar (iface : interface_state_t) (reminders : three_month_rem_t) : unit = let sel_tm = Unix.localtime (timestamp_of_line iface iface.left_selection) and today_tm = Unix.localtime (Unix.time()) in let cal = reminders.curr_cal in let acs = get_acs_codes () in Rcfile.color_on iface.scr.calendar_win Rcfile.Right_divider; wattron iface.scr.calendar_win A.bold; mvwvline iface.scr.calendar_win 0 0 acs.Acs.vline iface.scr.cw_lines; Rcfile.color_off iface.scr.calendar_win Rcfile.Right_divider; let hspacer = (iface.scr.cw_cols - 20) / 2 in let vspacer = (iface.scr.cw_lines - 8) / 2 in assert (wmove iface.scr.calendar_win vspacer hspacer); wclrtoeol iface.scr.calendar_win; Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_labels; wattron iface.scr.calendar_win A.bold; assert (waddstr iface.scr.calendar_win cal.Cal.title); wattroff iface.scr.calendar_win A.bold; assert (wmove iface.scr.calendar_win (vspacer + 1) hspacer); wclrtoeol iface.scr.calendar_win; assert (waddstr iface.scr.calendar_win cal.Cal.weekdays); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_labels; (* draw the day numbers *) let ws = Str.regexp " " in let rec draw_week weeks line = match weeks with | [] -> assert (wmove iface.scr.calendar_win line hspacer); wclrtoeol iface.scr.calendar_win | week :: tail -> let split_week = Str.full_split ws week in assert (wmove iface.scr.calendar_win line hspacer); wclrtoeol iface.scr.calendar_win; let rec draw_el elements = match elements with | [] -> () | el :: days -> begin match el with |Str.Delim s -> assert (waddstr iface.scr.calendar_win s) |Str.Text d -> let day = pred (int_of_string d) in if succ day = sel_tm.Unix.tm_mday then begin (* highlight selected day in reverse video *) wattron iface.scr.calendar_win A.reverse; (* assert (waddstr iface.scr.calendar_win d); *) end else (); if today_tm.Unix.tm_year = sel_tm.Unix.tm_year && today_tm.Unix.tm_mon = sel_tm.Unix.tm_mon && succ day = today_tm.Unix.tm_mday then begin (* highlight today's date *) Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_today; wattron iface.scr.calendar_win A.bold; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_today; wattroff iface.scr.calendar_win A.bold end else if reminders.curr_counts.(day) <= !Rcfile.busy_level1 then begin Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_level1; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_level1 end else if reminders.curr_counts.(day) <= !Rcfile.busy_level2 then begin Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_level2; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_level2 end else if reminders.curr_counts.(day) <= !Rcfile.busy_level3 then begin Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_level2; wattron iface.scr.calendar_win A.bold; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_level2; wattroff iface.scr.calendar_win A.bold end else if reminders.curr_counts.(day) <= !Rcfile.busy_level4 then begin Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_level3; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_level3 end else begin Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_level3; wattron iface.scr.calendar_win A.bold; assert (waddstr iface.scr.calendar_win d); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_level3; wattroff iface.scr.calendar_win A.bold end; wattroff iface.scr.calendar_win A.reverse end; draw_el days in draw_el split_week; draw_week tail (succ line) in draw_week cal.Cal.days (vspacer + 2); (* draw the week numbers *) if !Rcfile.number_weeks then begin let weeknum_col = hspacer + (utf8_len cal.Cal.weekdays) + 2 in Rcfile.color_on iface.scr.calendar_win Rcfile.Calendar_labels; assert (wmove iface.scr.calendar_win (vspacer + 1) weeknum_col); assert (waddch iface.scr.calendar_win acs.Acs.vline); assert (waddstr iface.scr.calendar_win "Wk#"); Rcfile.color_off iface.scr.calendar_win Rcfile.Calendar_labels; let rec print_weeknum weeknums line = match weeknums with | [] -> () | weeknum :: tail -> assert (wmove iface.scr.calendar_win (vspacer + line) weeknum_col); assert (waddch iface.scr.calendar_win acs.Acs.vline); assert (waddstr iface.scr.calendar_win weeknum); print_weeknum tail (succ line); in print_weeknum cal.Cal.weeknums 2; end else (); assert (wnoutrefresh iface.scr.calendar_win) (* Draw the untimed reminders window *) let draw_untimed (iface : interface_state_t) reminders = let lineinfo = Array.make iface.scr.uw_lines None in let blank = String.make iface.scr.uw_cols ' ' in let curr_ts = timestamp_of_line iface iface.left_selection in let today_reminders = Remind.get_untimed_reminders_for_day reminders curr_ts in werase iface.scr.untimed_win; let acs = get_acs_codes () in Rcfile.color_on iface.scr.untimed_win Rcfile.Right_divider; wattron iface.scr.untimed_win A.bold; assert (mvwaddch iface.scr.untimed_win 0 0 acs.Acs.ltee); mvwhline iface.scr.untimed_win 0 1 acs.Acs.hline (pred iface.scr.uw_cols); mvwvline iface.scr.untimed_win 1 0 acs.Acs.vline (pred iface.scr.uw_lines); Rcfile.color_off iface.scr.untimed_win Rcfile.Right_divider; if not !Rcfile.untimed_bold then wattroff iface.scr.untimed_win A.bold else (); Rcfile.color_on iface.scr.untimed_win Rcfile.Untimed_reminder; (* make sure the cursor doesn't unexpectedly disappear *) let iface = if iface.selected_side = Right && iface.right_selection > List.length today_reminders then if List.length today_reminders = 0 then { iface with right_selection = 1; } else { iface with right_selection = List.length today_reminders } else iface in let rec render_lines rem_list n line = match rem_list with |[] -> if n = 0 && iface.selected_side = Right then begin wattron iface.scr.untimed_win A.reverse; trunc_mvwaddstr iface.scr.untimed_win line 2 (iface.scr.uw_cols - 3) blank; wattroff iface.scr.untimed_win A.reverse end else () |rem :: tail -> if line < iface.scr.uw_lines then if n >= iface.top_untimed then begin if line = iface.right_selection && iface.selected_side = Right then wattron iface.scr.untimed_win A.reverse else wattroff iface.scr.untimed_win A.reverse; trunc_mvwaddstr iface.scr.untimed_win line 2 (iface.scr.uw_cols - 3) ("* " ^ rem.ur_msg); let curr_lineinfo = { ul_filename = rem.ur_filename; ul_linenum = rem.ur_linenum; ul_msg = rem.ur_msg } in lineinfo.(line) <- Some curr_lineinfo; render_lines tail (succ n) (succ line) end else render_lines tail (succ n) line else () in render_lines today_reminders 0 1; Rcfile.color_off iface.scr.untimed_win Rcfile.Untimed_reminder; wattroff iface.scr.untimed_win (A.bold lor A.reverse); (* if there's not enough window space to display all untimed reminders, display * arrows to indicate scrolling ability *) if iface.top_untimed > 0 then begin assert (mvwaddch iface.scr.untimed_win 1 (pred iface.scr.uw_cols) (int_of_char '^')); assert (mvwaddch iface.scr.untimed_win 2 (pred iface.scr.uw_cols) (int_of_char '^')) end else (); if List.length today_reminders > pred iface.scr.uw_lines + iface.top_untimed then begin assert (mvwaddch iface.scr.untimed_win (pred iface.scr.uw_lines) (pred iface.scr.uw_cols) (int_of_char 'v')); assert (mvwaddch iface.scr.untimed_win (iface.scr.uw_lines - 2) (pred iface.scr.uw_cols) (int_of_char 'v')) end else (); assert (wnoutrefresh iface.scr.untimed_win); {iface with untimed_lineinfo = lineinfo; len_untimed = List.length today_reminders} (* Draw the message window *) let draw_msg iface = let sel_tm = Unix.localtime (timestamp_of_line iface iface.left_selection) in let day_s = Printf.sprintf "%s, %s %.2d" (full_string_of_tm_wday sel_tm.Unix.tm_wday) (full_string_of_tm_mon sel_tm.Unix.tm_mon) sel_tm.Unix.tm_mday in let day_time_s = match iface.selected_side with |Left -> day_s ^ " at " ^ if !Rcfile.selection_12_hour then twelve_hour_string sel_tm else twentyfour_hour_string sel_tm |Right -> day_s in for i = 0 to pred iface.scr.mw_lines do assert (wmove iface.scr.msg_win i 0); wclrtoeol iface.scr.msg_win done; (* draw the date stamp *) Rcfile.color_on iface.scr.msg_win Rcfile.Selection_info; wattron iface.scr.msg_win (A.bold lor A.underline); trunc_mvwaddstr iface.scr.msg_win 0 0 iface.scr.mw_cols day_time_s; Rcfile.color_off iface.scr.msg_win Rcfile.Selection_info; wattroff iface.scr.msg_win (A.bold lor A.underline); (* draw the current date *) let curr_tm = Unix.localtime (Unix.time ()) in Rcfile.color_on iface.scr.msg_win Rcfile.Status; wattron iface.scr.msg_win A.bold; let curr_tm_str = if !Rcfile.status_12_hour then twelve_hour_string curr_tm else twentyfour_hour_string curr_tm in let s = Printf.sprintf "Wyrd v%s Currently: %s, %s %.2d at %s" Version.version (full_string_of_tm_wday curr_tm.Unix.tm_wday) (full_string_of_tm_mon curr_tm.Unix.tm_mon) curr_tm.Unix.tm_mday curr_tm_str in trunc_mvwaddstr iface.scr.msg_win (pred iface.scr.mw_lines) 0 iface.scr.mw_cols s; Rcfile.color_off iface.scr.msg_win Rcfile.Status; wattroff iface.scr.msg_win A.bold; (* draw the full MSG string, word wrapping as necessary *) let pad = String.make 16 ' ' in let rec render_desc times descriptions output = let rec render_line lines temp_output = match lines with |[] -> temp_output |line :: lines_tail -> render_line lines_tail ((pad ^ line) :: temp_output) in match descriptions with |[] -> List.rev output |desc :: desc_tail -> let time_str = Str.string_before ((List.hd times) ^ pad) 16 in let first_line = time_str ^ (List.hd desc) in render_desc (List.tl times) desc_tail ((render_line (List.tl desc) []) @ first_line :: output) in let (times, descriptions) = match iface.selected_side with |Left -> begin match iface.timed_lineinfo.(iface.left_selection) with |[] -> ([""], [["(no reminder selected)"]]) |rem_list -> let sorted_rem_list = List.fast_sort sort_lineinfo rem_list in let get_times tline = tline.tl_timestr in let get_lines tline = word_wrap tline.tl_msg (iface.scr.mw_cols - 24) in (List.rev_map get_times sorted_rem_list, List.rev_map get_lines sorted_rem_list) end |Right -> begin match iface.untimed_lineinfo.(iface.right_selection) with |None -> ([""], [["(no reminder selected)"]]) |Some uline -> ([""], [word_wrap uline.ul_msg (iface.scr.mw_cols - 24)]) end in let desc_lines = render_desc times descriptions [] in (* draw the pre-rendered lines to the screen *) Rcfile.color_on iface.scr.msg_win Rcfile.Description; let rec draw_desc_lines lines start line_num = match lines with |[] -> () |line :: tail -> if start > 0 then draw_desc_lines tail (pred start) line_num else if line_num < pred iface.scr.mw_lines then begin assert (mvwaddstr iface.scr.msg_win line_num 5 line); draw_desc_lines tail start (succ line_num) end else () in let adjusted_top = let max_top = max ((List.length desc_lines) - iface.scr.mw_lines + 2) 0 in min iface.top_desc max_top in draw_desc_lines desc_lines adjusted_top 1; if adjusted_top > 0 then begin assert (mvwaddch iface.scr.msg_win 1 (iface.scr.mw_cols - 1) (int_of_char '^')); assert (mvwaddch iface.scr.msg_win 2 (iface.scr.mw_cols - 1) (int_of_char '^')) end else (); if adjusted_top < List.length desc_lines - iface.scr.mw_lines + 2 then begin assert (mvwaddch iface.scr.msg_win (iface.scr.mw_lines - 2) (iface.scr.mw_cols - 1) (int_of_char 'v')); assert (mvwaddch iface.scr.msg_win (iface.scr.mw_lines - 3) (iface.scr.mw_cols - 1) (int_of_char 'v')) end else (); Rcfile.color_off iface.scr.msg_win Rcfile.Description; assert (wnoutrefresh iface.scr.msg_win); {iface with top_desc = adjusted_top} (* Draw a message in the error window. If draw_cursor = true, then * add a blinking cursor at the end of the message. *) let draw_error iface err draw_cursor = werase iface.scr.err_win; trunc_mvwaddstr iface.scr.err_win 0 0 iface.scr.ew_cols err; let len = utf8_len err in if draw_cursor && len <= pred iface.scr.ew_cols then begin wattron iface.scr.err_win A.blink; assert (mvwaddch iface.scr.err_win 0 len (int_of_char '_')); wattroff iface.scr.err_win A.blink end else (); assert (wnoutrefresh iface.scr.err_win) (* Draw a selection dialog. *) let draw_selection_dialog (iface : interface_state_t) (title : string) (elements : string list) (selection : int) (top : int) = erase (); (* draw the title *) Rcfile.color_on iface.scr.stdscr Rcfile.Help; attron A.bold; trunc_mvwaddstr iface.scr.stdscr 0 0 iface.scr.cols title; Rcfile.color_off iface.scr.stdscr Rcfile.Help; attroff A.bold; (* draw the list elements *) Rcfile.color_on iface.scr.stdscr Rcfile.Untimed_reminder; let rec draw_element el_list line count = match el_list with | [] -> () | el :: tail -> if count >= top && line < iface.scr.lines then begin if count = selection then begin attron A.reverse; trunc_mvwaddstr iface.scr.stdscr line 2 (iface.scr.cols - 4) el; attroff A.reverse; end else trunc_mvwaddstr iface.scr.stdscr line 2 (iface.scr.cols - 4) el; draw_element tail (succ line) (succ count) end else draw_element tail line (succ count) in draw_element elements 1 0; (* if there's not enough window space to display all reminder files, display * arrows to indicate scrolling ability *) if top > 0 then begin assert (mvaddch 1 (iface.scr.cols - 2) (int_of_char '^')); assert (mvaddch 2 (iface.scr.cols - 2) (int_of_char '^')) end else (); if List.length elements > pred iface.scr.lines + top then begin assert (mvaddch (pred iface.scr.lines) (iface.scr.cols - 2) (int_of_char 'v')); assert (mvaddch (iface.scr.lines - 2) (iface.scr.cols - 2) (int_of_char 'v')) end else (); Rcfile.color_off iface.scr.stdscr Rcfile.Untimed_reminder; assert (refresh ()) (* arch-tag: DO_NOT_CHANGE_9ff0fd0c-6eb1-410f-8fcf-6dfcf94b346a *) wyrd-1.4.4/README0000644000175000017500000000025010757447265012067 0ustar paulpaulWyrd README file ------------------------------------------------------------------------ Please see the 'doc' subdirectory for installation and usage instructions. wyrd-1.4.4/time_lang.ml0000644000175000017500000005272710757447265013520 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* time_lang.ml * * This module implements a regexp-based parser for natural-language descriptions of * events. It recognizes most reasonable permutations of ([DATE] [TIME] DESCRIPTION), * including: * * "do some stuff tomorrow at 3" * "wednesday meeting with Bob 1:30pm-3:00" * "leave for airport noon next Fri" * "6/14 6pm dinner with Tom" * * Preference is generally for US time and date conventions; would be quite difficult to * internationalize this module. *) exception Event_parse_error of string let parse_failwith s = raise (Event_parse_error s) let parse_fail_default () = parse_failwith "unrecognized format for event." type event_t = Timed of (Unix.tm * Unix.tm) | Untimed of Unix.tm (* DEFINE TIME AND DATE REGEXES *) (* Note: careful when changing these regexps. If the grouping tree changes, * then the fields may be misnumbered in code below. *) (* Note: ocaml _really_ needs a raw string syntax to make regexps look more sane... *) let weekdays = "\\(\\(on[ \t]+\\)?\\(next[ \t]+\\)?" ^ "\\(\\(sunday\\|sun\\)\\|\\(monday\\|mon\\)\\|\\(tuesday\\|tue\\|tues\\)\\|" ^ "\\(wednesday\\|wed\\)\\|\\(thursday\\|thu\\|thur\\|thurs\\)\\|" ^ "\\(friday\\|fri\\)\\|\\(saturday\\|sat\\)\\)\\)" (* typical US-style dates, like 6/1 or 6/1/2006 *) let numeric_slash_date = "\\(\\([0-9]+\\)/\\([0-9]+\\)\\(/\\([0-9][0-9][0-9][0-9]\\)\\)?\\)" (* ISO standard dates, like 2006-06-01 *) let iso_date = "\\(\\([0-9][0-9][0-9][0-9]\\)-\\([0-9]+\\)-\\([0-9]+\\)\\)" let numeric_date = "\\(\\(on[ \t]+\\)?\\(" ^ numeric_slash_date ^ "\\|" ^ iso_date ^ "\\)\\)" let short_date = "\\(\\(today\\)\\|\\(tomorrow\\)\\|" ^ "\\(in[ \t]+\\([0-9]+\\)[ \t]+day\\(s\\|s' time\\)?\\)\\)" let date_spec = "\\(" ^ weekdays ^ "\\|" ^ numeric_date ^ "\\|" ^ short_date ^ "\\)" (* 5, or 5:30, or 5pm, or 5:30 pm *) let time_spec = "\\(\\(\\([0-9][0-9]?\\)\\(:\\([0-9][0-9]\\)\\)?[ \t]*\\(am\\|pm\\)?\\)\\|" ^ "\\(noon\\|midnight\\)\\)" (* either match a single time spec, or match a pair formatted as a range: * 5-7 or 5:30pm-7 or 5 until 7 or 5:30 to 7pm ... *) let time_range_spec = "\\(\\(at[ \t]+\\)?" ^ time_spec ^ "\\([ \t]*\\(-\\|to\\|\\until\\)[ \t]*" ^ time_spec ^ "\\)?\\)" let date_start_regex = Str.regexp_case_fold ("[ \t,.]*" ^ date_spec ^ "[ \t,.]+") let time_start_regex = Str.regexp_case_fold ("[ \t,.]*" ^ time_range_spec ^ "[ \t,.]+") let date_end_regex = Str.regexp_case_fold ("[ \t,.]+" ^ date_spec ^ "[ \t,.]*$") let time_end_regex = Str.regexp_case_fold ("[ \t,.]+" ^ time_range_spec ^ "[ \t,.]*$") (* given a current time and an hour/minute/merid specifier, * search forward from current time and provide the next time * value that satisfies the spec. *) (* 'future' is a boolean variable that determines whether the time * is required to be in the future or not (i.e. the present is acceptable) *) let next_matching_time future curr_tm hour min merid = let (curr, _) = Unix.mktime curr_tm in let get_tm hour_shift day_shift = let tm = { curr_tm with Unix.tm_hour = hour + hour_shift; Unix.tm_min = min; Unix.tm_sec = 0; Unix.tm_mday = curr_tm.Unix.tm_mday + day_shift } in Unix.mktime tm in if merid = "am" then (* if "am" is specified... *) (* try using the hour and minute as given *) let (start1, start1_tm) = get_tm 0 0 in if start1 > curr || (start1 = curr && not future) then start1_tm else (* if that fails, just use the same time tomorrow *) let (start2, start2_tm) = get_tm 0 1 in start2_tm else if merid = "pm" then (* if "pm" is specified... *) (* try using the hour and minute as given (but shifted to afternoon) *) let (start1, start1_tm) = get_tm 12 0 in if start1 > curr || (start1 = curr && not future) then start1_tm else (* if that fails, use the same time tomorrow *) let (start2, start2_tm) = get_tm 12 1 in start2_tm else (* if neither "am" nor "pm" are specified... *) (* first use the hour and minute as given *) let (start1, start1_tm) = get_tm 0 0 in if start1 > curr || (start1 = curr && not future) then start1_tm else (* if that fails, look in the afternoon *) let (start2, start2_tm) = get_tm 12 0 in if start2 > curr || (start2 = curr && not future) then start2_tm else (* if that fails, shift to tomorrow morning *) let (start3, start3_tm) = get_tm 0 1 in start3_tm (* Find the next timespec following curr_tm that falls on 'wday'. 'next_week' * is a boolean variable that is true if the event should be interpreted * as occurring next week. *) let find_next_wday curr_tm wday next_week = (* start scanning forward from the current timespec, unless the 'next' * specifier is given; in that case, start from the beginning of * next week *) let scan_from = if next_week then let week_diff = if !Rcfile.week_starts_monday then 7 - ((curr_tm.Unix.tm_wday + 6) mod 7) else 7 - curr_tm.Unix.tm_wday in let temp = { curr_tm with Unix.tm_mday = curr_tm.Unix.tm_mday + week_diff; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm else curr_tm in let diff = if wday > scan_from.Unix.tm_wday then wday - scan_from.Unix.tm_wday else if wday = scan_from.Unix.tm_wday && next_week then 0 else wday - scan_from.Unix.tm_wday + 7 in let temp = { scan_from with Unix.tm_mday = scan_from.Unix.tm_mday + diff; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm (* Find the next timespec following curr_tm that satisfies the * month and day provided. *) let find_next_mon_mday curr_tm mon mday = if mon > curr_tm.Unix.tm_mon then let temp = { curr_tm with Unix.tm_mon = mon; Unix.tm_mday = mday; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm else if mon = curr_tm.Unix.tm_mon && mday > curr_tm.Unix.tm_mday then let temp = { curr_tm with Unix.tm_mday = mday; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm else let temp = { curr_tm with Unix.tm_year = succ curr_tm.Unix.tm_year; Unix.tm_mon = mon; Unix.tm_mday = mday; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm (* Parse a natural language date string. *) let parse_natural_language_date date_str = let current = Unix.localtime (Unix.time ()) in let (_, current_tm) = Unix.mktime current in let date_regex = Str.regexp date_spec in if Str.string_match date_regex date_str 0 then begin (* for i = 1 to 30 do try Printf.printf "%2d: \"%s\"\n" i (Str.matched_group i date_str); flush stdout; with Not_found -> () done; *) let get_field num = Str.matched_group num date_str in let handle_weekday () = let has_next = try let _ = get_field 4 in true with Not_found -> false in try (* some variant of "sunday" *) let _ = get_field 6 in find_next_wday current_tm 0 has_next with Not_found -> try (* some variant of "monday" *) let _ = get_field 7 in find_next_wday current_tm 1 has_next with Not_found -> try (* some variant of "tuesday" *) let _ = get_field 8 in find_next_wday current_tm 2 has_next with Not_found -> try (* some variant of "wednesday" *) let _ = get_field 9 in find_next_wday current_tm 3 has_next with Not_found -> try (* some variant of "thursday" *) let _ = get_field 10 in find_next_wday current_tm 4 has_next with Not_found -> try (* some variant of "friday" *) let _ = get_field 11 in find_next_wday current_tm 5 has_next with Not_found -> try (* some variant of "saturday" *) let _ = get_field 12 in find_next_wday current_tm 6 has_next with Not_found -> parse_failwith "please submit a bug report for \"unreachable case 3\"." in let handle_numeric_slash () = try (* US-style numeric date specified with slashes *) let first = int_of_string (get_field 17) in let second = int_of_string (get_field 18) in let (month, monthday) = if !Rcfile.quick_date_US then (* assume US conventions (month first, then day of month) *) (first, second) else (* assume non-US conventions (day of month first, then month) *) (second, first) in if month >= 1 && month <= 12 && monthday >= 1 && monthday <= 31 then begin try let third = int_of_string (get_field 20) in if third >= 1991 && third <= 2037 then let temp = { current_tm with Unix.tm_year = third - 1900; Unix.tm_mon = pred month; Unix.tm_mday = monthday; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm else parse_fail_default () with Not_found -> find_next_mon_mday current_tm (pred month) monthday end else parse_fail_default () with Not_found -> parse_failwith "please submit a bug report for \"unreachable case 4\"." in let handle_iso () = try (* iso numeric date specified with dashes *) let first = int_of_string (get_field 22) in let second = int_of_string (get_field 23) in let third = int_of_string (get_field 24) in if first >= 1991 && first <= 2037 && second >= 1 && second <= 12 && third >= 1 && third <= 31 then let temp = { current_tm with Unix.tm_year = first - 1900; Unix.tm_mon = pred second; Unix.tm_mday = third; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm else parse_fail_default () with Not_found -> parse_failwith "please submit a bug report for \"unreachable case 5\"." in let handle_short () = try (* "today" *) let _ = get_field 26 in let temp = { current_tm with Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm with Not_found -> try (* "tomorrow" *) let _ = get_field 27 in let temp = { current_tm with Unix.tm_mday = succ current_tm.Unix.tm_mday; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm with Not_found -> try (* "in N days" *) let num = int_of_string (get_field 29) in let temp = { current_tm with Unix.tm_mday = current_tm.Unix.tm_mday + num; Unix.tm_hour = 0; Unix.tm_min = 0; Unix.tm_sec = 0 } in let (_, norm) = Unix.mktime temp in norm with Not_found -> parse_failwith "please submit a bug report for \"unreachable case 6\"." in let date_tm = try (* a weekday specifier *) let _ = get_field 5 in handle_weekday () with Not_found -> try (* a numeric date specifier with slashes *) let _ = get_field 16 in handle_numeric_slash () with Not_found -> try (* a numeric date specifier with dashes *) let _ = get_field 21 in handle_iso () with Not_found -> try (* a shortcut date *) let _ = get_field 25 in handle_short () with Not_found -> parse_failwith "please submit a bug report for \"unreachable case 2\"." in date_tm end else parse_failwith "please submit a bug report for \"unreachable case 1\"." (* Parse a natural language time string. *) (* 'future' is a boolean variable that determines whether the time * is required to be in the future or not (i.e. the present is acceptable) *) let parse_natural_language_time future current_tm time_str = let time_regex = Str.regexp time_range_spec in if Str.string_match time_regex time_str 0 then begin (* for i = 1 to 30 do try Printf.printf "%2d: \"%s\"\n" i (Str.matched_group i time_str); flush stdout; with | Not_found -> () done; *) let get_field num = try Str.matched_group num time_str with Not_found -> "" in let start_hour_s = get_field 5 and start_minute_s = get_field 7 and start_meridien_s = get_field 8 and end_hour_s = get_field 14 and end_minute_s = get_field 16 and end_meridien_s = get_field 17 and start_abbrev = get_field 9 and end_abbrev = get_field 18 in (* OK, given a timestamp as context, try to choose the most sensible * interpretation of the time spec. Search forward from current time for * the first start time that matches, then continue searching forward * for the first end time that matches. *) let (start_hour, start_meridien) = if start_abbrev = "noon" then (0, "pm") else if start_abbrev = "midnight" then (0, "am") else if start_hour_s = "" then parse_fail_default () else let temp = int_of_string start_hour_s in if temp = 0 then (0, "am") else if temp >= 13 && temp <= 23 then (temp - 12, "pm") else if temp >= 1 && temp <= 11 then (temp, start_meridien_s) else if temp = 12 then (0, start_meridien_s) else parse_fail_default () in let start_minute = if start_minute_s = "" then 0 else let temp = int_of_string start_minute_s in if temp >= 0 && temp <= 59 then temp else parse_fail_default () in let start_tm = next_matching_time future current_tm start_hour start_minute start_meridien in let end_tm = if end_hour_s = "" && end_abbrev = "" then start_tm else let (end_hour, end_meridien) = if end_abbrev = "noon" then (0, "pm") else if end_abbrev = "midnight" then (0, "am") else let temp = int_of_string end_hour_s in if temp = 0 then (0, "am") else if temp >= 13 && temp <= 23 then (temp - 12, "pm") else if temp >= 1 && temp <= 11 then (temp, end_meridien_s) else if temp = 12 then (0, end_meridien_s) else parse_fail_default () in let end_minute = if end_minute_s = "" then 0 else let temp = int_of_string end_minute_s in if temp >= 0 && temp <= 59 then temp else parse_fail_default () in next_matching_time true start_tm end_hour end_minute end_meridien in (start_tm, end_tm) end else parse_failwith "please submit a bug report for \"unreachable case 10\"." (* at the beginning of the string, searches for date, then time, * then date again, then time again, as necessary *) let rec find_date_time_begin date time event_remainder attempts = let find_element_gen element_start_regex element event_s = match element with | None -> if Str.string_match element_start_regex event_s 0 then begin let new_element = String.lowercase (Str.matched_group 1 event_s) in let pos = Str.match_end () in let new_event_s = Str.string_after event_s pos in ((Some new_element), new_event_s) end else (element, event_s) | Some _ -> (element, event_s) in let find_date = find_element_gen date_start_regex in let find_time = find_element_gen time_start_regex in if attempts >= 2 then (date, time, event_remainder) else let (new_date, event_remainder2) = find_date date event_remainder in let (new_time, event_remainder3) = find_time time event_remainder2 in find_date_time_begin new_date new_time event_remainder3 (succ attempts) (* at the end of the string, searches for date, then time, * then date again, then time again, as necessary *) let rec find_date_time_end date time event_remainder attempts = let find_element_gen element_end_regex element event_s = match element with | None -> begin try let pos = Str.search_forward element_end_regex event_s 0 in let new_element = String.lowercase (Str.matched_group 1 event_s) in let new_event_s = Str.string_before event_s pos in ((Some new_element), new_event_s) with Not_found -> (element, event_s) end | Some _ -> (element, event_s) in let find_date = find_element_gen date_end_regex in let find_time = find_element_gen time_end_regex in if attempts >= 2 then (date, time, event_remainder) else let (new_date, event_remainder2) = find_date date event_remainder in let (new_time, event_remainder3) = find_time time event_remainder2 in find_date_time_end new_date new_time event_remainder3 (succ attempts) (* Primary function of this module. Parses a natural language definition for an event, * which might look something like "Wednesday meeting with Bob at 9:30pm." *) let parse_natural_language_event event_str = let (date, time, description) = (* search at the start of the string first, then at the end *) let (date_begin, time_begin, remainder) = find_date_time_begin None None event_str 0 in find_date_time_end date_begin time_begin remainder 0 in let curr_tm = Unix.localtime (Unix.time ()) in let rem_spec = match date with | None -> begin match time with | None -> parse_fail_default () | Some time_str -> Timed (parse_natural_language_time true curr_tm time_str) end | Some date_str -> let date_tm = parse_natural_language_date date_str in begin match time with | None -> Untimed date_tm | Some time_str -> Timed (parse_natural_language_time false date_tm time_str) end in (rem_spec, description) (* arch-tag: DO_NOT_CHANGE_a43ce66f-688e-42dd-8c2b-83b55c124a5a *) wyrd-1.4.4/remind.ml0000644000175000017500000006411510757447265013031 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* remind.ml * functions for interfacing with 'remind(1)' *) exception Occurrence_not_found open Utility (* A record for an individual timed reminder, as read from * the output of 'remind -s'. *) type timed_rem_t = { tr_start : float; tr_end : float; tr_msg : string; tr_filename : string; tr_linenum : string; tr_has_weight : bool } (* A record for an individual untimed reminder, as read from * the output of 'remind -s'. *) type untimed_rem_t = { ur_start : float; ur_msg : string; ur_filename : string; ur_linenum : string; ur_has_weight : bool } (* Storage for a three-month window of reminders and * the calendar for the current month. * Makes it possible to handle edge effects of moving * from month to month without constantly calling * rem(1) and regenerating calendar layouts. * * Timed reminders are stored in an array of lists, * with each element of the array representing a different * indentation level on the timetable. Untimed reminders * have no indentation, so they are simply stored in * lists. *) type three_month_rem_t = { curr_timestamp : float; prev_timed : timed_rem_t list array; curr_timed : timed_rem_t list array; next_timed : timed_rem_t list array; all_timed : timed_rem_t list array; prev_untimed : untimed_rem_t list; curr_untimed : untimed_rem_t list; next_untimed : untimed_rem_t list; all_untimed : untimed_rem_t list; curr_counts : int array; curr_cal : Cal.t; remind_error : string } (* Get the starting timestamp and time record for a given month *) let month_start_of_tm tm = let month_start_tm = {empty_tm with Unix.tm_mon = tm.Unix.tm_mon; Unix.tm_year = tm.Unix.tm_year; } in Unix.mktime month_start_tm (* Process information about a timed reminder, create a new reminder * record for it, and store it in the timed reminders array at the * proper indentation level. * * The indentation levels are determined by maintaining an array that indicates * which levels have been used for each hourly timeslot. As each reminder is * processed, we look into the array to find the smallest indentation level * available. Complexity is approximately * (number of reminders) * (average reminder duration). Since indentation is * determined a month at a time, there may be some minor discrepancies at * month borders. *) let process_timed tm duration_s month_start_ts indentations partial_trem timed = let (f_rem_ts, _) = Unix.mktime tm in let duration = if duration_s = "*" then 0.0 else float_of_string duration_s in (* compute the indentation level *) (* top_index and bottom_index provide the range of row indices into * array indentations that are covered by this reminder *) let top_index = try int_of_float ((f_rem_ts -. month_start_ts) /. 3600.0) with _ -> 0 in let bottom_index = try let real_bottom_index = let shift = if duration > 0.0 then (f_rem_ts +. (duration *. 60.0) -. month_start_ts) /. 3600.0 else (f_rem_ts +. (duration +. 60.0) -. month_start_ts) /. 3600.0 in (* catch the edge effects when reminders end on hour boundaries *) if shift = float_of_int (int_of_float shift) then pred (int_of_float shift) else int_of_float shift in (* the bottom index could flow off of this month, in which case * we truncate and hope everything works out *) if real_bottom_index > pred (Array.length indentations) then pred (Array.length indentations) else real_bottom_index with _ -> top_index in (* locate the smallest free indentation level *) let rec find_indent level = if level < Array.length indentations.(0) then begin let collision = ref false in for i = top_index to bottom_index do if indentations.(i).(level) then collision := true else () done; if !collision then find_indent (succ level) else begin for i = top_index to bottom_index do indentations.(i).(level) <- true done; level end end else (* give up and default to maximum indentation *) pred (Array.length indentations.(0)) in let indent = find_indent 0 in let trem = {partial_trem with tr_start = f_rem_ts; tr_end = f_rem_ts +. (duration *. 60.); } in timed.(indent) <- trem :: timed.(indent) (* Obtain two lists of reminders for the month of the timestamp argument. * The first list is for timed reminders, the second is for untimed. * The timed reminders list also provides the indentation levels that * draw_timed should use to render each reminder. * * The indentation levels are determined by maintaining an array that indicates * which levels have been used for each hourly timeslot. As each reminder is * processed, we look into the array to find the smallest indentation level * available. Complexity is approximately * (number of reminders) * (average reminder duration). Since indentation is * determined a month at a time, there may be some minor discrepancies at * month borders. * * The optional argument 'suppress_advwarn', if true, will override * the "advance_warning" rcfile option. *) let month_reminders ?(suppress_advwarn=false) timestamp = let comment_regex = Str.regexp "^#.*fileinfo \\([^ ]+\\) \\(.*\\)$" in let rem_regex = Str.regexp "\\([^ ]+\\) [^ ]+ \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\) \\(.*\\)$" in let nodisplay_regex = Str.regexp_case_fold ".*nodisplay" in let noweight_regex = Str.regexp_case_fold ".*noweight" in let tm = Unix.localtime timestamp in let rem_date_str = (string_of_tm_mon tm.Unix.tm_mon) ^ " " ^ (string_of_int tm.Unix.tm_mday) ^ " " ^ (string_of_int (tm.Unix.tm_year + 1900)) in let remind_s_flag = if suppress_advwarn then " -s" else if !Rcfile.advance_warning then " -sa" else " -s" in let full_remind_command = !Rcfile.remind_command ^ remind_s_flag ^ " -l -g -b2 " ^ !Rcfile.reminders_file ^ " " ^ rem_date_str in let (out_lines, err_lines) = Utility.read_all_shell_command_output full_remind_command in (* check for Remind errors *) let remind_err = if List.length err_lines > 0 then List.hd err_lines else "" in let num_indentations = 4 in let indentations = Array.make_matrix (24 * 31) num_indentations false in let (month_start_ts, _) = month_start_of_tm tm in let timed = Array.make num_indentations [] in let rec build_lists lines untimed = begin match lines with | [] -> for i = 0 to pred (Array.length timed) do timed.(i) <- List.rev timed.(i) done; (remind_err, timed, List.rev untimed) | comment_line :: rem_line :: lines_tail -> begin try if Str.string_match comment_regex comment_line 0 then begin let line_num_s = Str.matched_group 1 comment_line and filename = Str.matched_group 2 comment_line in if Str.string_match rem_regex rem_line 0 then begin let date_s = Str.matched_group 1 rem_line and tag = Str.matched_group 2 rem_line and duration_s = Str.matched_group 3 rem_line and min_s = Str.matched_group 4 rem_line and msg = Str.matched_group 5 rem_line in (* further subdivide the date string *) let date_arr = Array.of_list (Str.split (Str.regexp "[/-]") date_s) in let year = int_of_string date_arr.(0) and month = int_of_string date_arr.(1) and day = int_of_string date_arr.(2) in let temp = {empty_tm with Unix.tm_mday = day; Unix.tm_mon = pred month; Unix.tm_year = year - 1900; } in (* check whether this reminder is tagged 'nodisplay' *) if (Str.string_match nodisplay_regex tag 0) then (* skip this reminder due to a 'nodisplay' tag *) build_lists lines_tail untimed else begin let has_weight = not (Str.string_match noweight_regex tag 0) in if min_s = "*" then (* if minutes are not provided, this must be an untimed reminder *) let (f_rem_ts, _) = Unix.mktime temp in let urem = { ur_start = f_rem_ts; ur_msg = msg; ur_filename = filename; ur_linenum = line_num_s; ur_has_weight = has_weight } in build_lists lines_tail (urem :: untimed) else begin (* if minutes are provided, this must be a timed reminder *) let temp_with_min = {temp with Unix.tm_min = int_of_string min_s} in let partial_trem = { tr_start = 0.0; (* still needs to be filled in *) tr_end = 0.0; (* still needs to be filled in *) tr_msg = msg; tr_filename = filename; tr_linenum = line_num_s; tr_has_weight = has_weight } in process_timed temp_with_min duration_s month_start_ts indentations partial_trem timed; build_lists lines_tail untimed end end end else (* if there was no rem_regex match, continue with next line *) build_lists (rem_line :: lines_tail) untimed end else (* if there was no comment_regex match, continue with next line *) build_lists (rem_line :: lines_tail) untimed with _ -> (* if there's an error in regexp matching or string coersion, * just drop that reminder and go to the next line *) build_lists (rem_line :: lines_tail) untimed end | comment_line :: [] -> (* this line doesn't conform to the spec, so throw it out *) build_lists [] untimed end in build_lists out_lines [] (* generate a count of how many reminders fall on any given day of * the month *) let count_reminders month_start_tm timed untimed = let rem_counts = Array.make 31 0 in let count_rems start has_weight = let tm = Unix.localtime start in if has_weight && tm.Unix.tm_year = month_start_tm.Unix.tm_year && tm.Unix.tm_mon = month_start_tm.Unix.tm_mon then let day = pred tm.Unix.tm_mday in rem_counts.(day) <- succ rem_counts.(day) else () in let count_timed rem = count_rems rem.tr_start rem.tr_has_weight in let count_untimed rem = count_rems rem.ur_start rem.ur_has_weight in Array.iter (List.iter count_timed) timed; List.iter count_untimed untimed; rem_counts (* generate a count of how many hours of reminders one has on * any given day of the month. Note: some minor errors can * occur during DST, but this is too small to worry about. *) let count_busy_hours month_start_tm timed untimed = let hour_counts = Array.make 31 0.0 in let last_day = let temp = {month_start_tm with Unix.tm_mday = 32} in let (_, nextmonth) = Unix.mktime temp in 32 - nextmonth.Unix.tm_mday in let count_hours start stop has_weight = if has_weight then for day = 1 to last_day do let day_tm = {month_start_tm with Unix.tm_mday = day} in let (day_ts, _) = Unix.mktime day_tm in if day_ts >= start then if stop > day_ts +. 86400. then hour_counts.(pred day) <- hour_counts.(pred day) +. 24. else if stop > day_ts then hour_counts.(pred day) <- hour_counts.(pred day) +. ((stop -. day_ts) /. 3600.) else () else if day_ts +. 86400. > start then if stop > day_ts +. 86400. then hour_counts.(pred day) <- hour_counts.(pred day) +. 24. -. ((start -. day_ts) /. 3600.) else hour_counts.(pred day) <- hour_counts.(pred day) +. ((stop -. start) /. 3600.) else () done else () in let count_timed rem = count_hours rem.tr_start rem.tr_end rem.tr_has_weight in let count_untimed rem = let stop = rem.ur_start +. (!Rcfile.untimed_duration *. 60.) in count_hours rem.ur_start stop rem.ur_has_weight in Array.iter (List.iter count_timed) timed; List.iter count_untimed untimed; Array.map int_of_float hour_counts (* determine the busy-ness level for each day in the month *) let count_busy month_tm timed untimed = let month_start_tm = { month_tm with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0; Unix.tm_mday = 1 } in match !Rcfile.busy_algorithm with |1 -> count_reminders month_start_tm timed untimed |2 -> count_busy_hours month_start_tm timed untimed |_ -> Rcfile.config_failwith "busy_algorithm must be either 1 or 2" (* comparison functions for sorting reminders chronologically *) let cmp_timed rem_a rem_b = compare rem_a.tr_start rem_b.tr_start let cmp_untimed rem_a rem_b = compare rem_a.ur_start rem_b.ur_start (* take an array of timed reminder lists and merge them into * a single list sorted by starting timestamp *) let merge_timed timed = let all_rem = ref [] in for i = 0 to pred (Array.length timed) do all_rem := List.rev_append timed.(i) !all_rem done; List.fast_sort cmp_timed !all_rem (* same thing as List.append (or @), but tail-recursive *) let safe_append a b = List.rev_append (List.rev a) b (* initialize a new three-month reminder record *) let create_three_month ?(suppress_advwarn=false) timestamp = let month_start_tm = { Unix.localtime timestamp with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0; Unix.tm_mday = 1 } in let (curr_ts, _) = Unix.mktime month_start_tm in let temp_prev = { month_start_tm with Unix.tm_mon = pred month_start_tm.Unix.tm_mon } in let temp_next = { month_start_tm with Unix.tm_mon = succ month_start_tm.Unix.tm_mon } in let (prev_ts, _) = Unix.mktime temp_prev and (next_ts, _) = Unix.mktime temp_next in let (pre, pt, pu) = month_reminders ~suppress_advwarn:suppress_advwarn prev_ts in let (cre, ct, cu) = month_reminders ~suppress_advwarn:suppress_advwarn curr_ts in let (nre, nt, nu) = month_reminders ~suppress_advwarn:suppress_advwarn next_ts in let at = Array.make (Array.length pt) [] in for i = 0 to pred (Array.length at) do at.(i) <- safe_append pt.(i) (safe_append ct.(i) nt.(i)) done; let err_str = if String.length pre > 0 then pre else if String.length cre > 0 then cre else nre in let au = safe_append pu (safe_append cu nu) in { curr_timestamp = curr_ts; prev_timed = pt; curr_timed = ct; next_timed = nt; all_timed = at; prev_untimed = pu; curr_untimed = cu; next_untimed = nu; all_untimed = au; curr_counts = count_busy month_start_tm at au; curr_cal = Cal.make curr_ts !Rcfile.week_starts_monday; remind_error = err_str } (* Update a three-month reminders record for the next month *) let next_month reminders = let curr_tm = Unix.localtime reminders.curr_timestamp in let temp1 = { curr_tm with Unix.tm_mon = succ curr_tm.Unix.tm_mon } in let temp2 = { curr_tm with Unix.tm_mon = curr_tm.Unix.tm_mon + 2 } in let (new_curr_timestamp, temp1) = Unix.mktime temp1 in let (next_timestamp, temp2) = Unix.mktime temp2 in let (re, t, u) = month_reminders next_timestamp in let at = Array.make (Array.length t) [] in for i = 0 to pred (Array.length t) do at.(i) <- safe_append reminders.curr_timed.(i) (safe_append reminders.next_timed.(i) t.(i)) done; let au = safe_append reminders.curr_untimed (safe_append reminders.next_untimed u) in { curr_timestamp = new_curr_timestamp; prev_timed = reminders.curr_timed; curr_timed = reminders.next_timed; next_timed = t; all_timed = at; prev_untimed = reminders.curr_untimed; curr_untimed = reminders.next_untimed; next_untimed = u; all_untimed = au; curr_counts = count_busy temp1 at au; curr_cal = Cal.make new_curr_timestamp !Rcfile.week_starts_monday; remind_error = re } (* Update a three-month reminders record for the previous month *) let prev_month reminders = let curr_tm = Unix.localtime reminders.curr_timestamp in let temp1 = { curr_tm with Unix.tm_mon = pred curr_tm.Unix.tm_mon } in let temp2 = { curr_tm with Unix.tm_mon = curr_tm.Unix.tm_mon - 2 } in let (new_curr_timestamp, temp1) = Unix.mktime temp1 in let (prev_timestamp, temp2) = Unix.mktime temp2 in let (re, t, u) = month_reminders prev_timestamp in let at = Array.make (Array.length t) [] in for i = 0 to pred (Array.length t) do at.(i) <- safe_append t.(i) (safe_append reminders.prev_timed.(i) reminders.curr_timed.(i)) done; let au = safe_append u (safe_append reminders.prev_untimed reminders.curr_untimed) in { curr_timestamp = new_curr_timestamp; prev_timed = t; curr_timed = reminders.prev_timed; next_timed = reminders.curr_timed; all_timed = at; prev_untimed = u; curr_untimed = reminders.prev_untimed; next_untimed = reminders.curr_untimed; all_untimed = au; curr_counts = count_busy temp1 at au; curr_cal = Cal.make new_curr_timestamp !Rcfile.week_starts_monday; remind_error = re } (* Return a new reminders record centered on the current timestamp, * doing as little work as possible. *) let update_reminders rem timestamp = let tm = Unix.localtime timestamp and rem_tm = Unix.localtime rem.curr_timestamp in if tm.Unix.tm_year = rem_tm.Unix.tm_year && tm.Unix.tm_mon = rem_tm.Unix.tm_mon then rem else let temp1 = { rem_tm with Unix.tm_mon = pred rem_tm.Unix.tm_mon } in let temp2 = { rem_tm with Unix.tm_mon = succ rem_tm.Unix.tm_mon } in let (_, prev_tm) = Unix.mktime temp1 in let (_, next_tm) = Unix.mktime temp2 in if tm.Unix.tm_year = prev_tm.Unix.tm_year && tm.Unix.tm_mon = prev_tm.Unix.tm_mon then prev_month rem else if tm.Unix.tm_year = next_tm.Unix.tm_year && tm.Unix.tm_mon = next_tm.Unix.tm_mon then next_month rem else create_three_month timestamp (* Look at all 'next' reminders after the given timestamp. Search * through the list for the first occurrence of the search regexp, and return * a timestamp for that date. * This calls 'remind -n' twice--once for the current day, once for the next day. * The second call is necessary because reminders falling on the current day * but before the current timestamp will effectively suppress later recurrences * of that reminder. * * We also have to make a separate check that the matched reminder is not tagged * with 'nodisplay'; since these reminders don't show up on the display, Wyrd * should not be able to match them. *) let find_next msg_regex timestamp = let rem_regex = Str.regexp "^\\([^ ]+\\)[/-]\\([^ ]+\\)[/-]\\([^ ]+\\) [^ ]+ \\([^ ]+\\) [^ ]+ \\([^ ]+\\) \\([^ ]+.*\\)$" in let nodisplay_regex = Str.regexp_case_fold ".*nodisplay" in let tm1 = Unix.localtime timestamp in let temp = {tm1 with Unix.tm_mday = succ tm1.Unix.tm_mday} in (* add 24 hours *) let (_, tm2) = Unix.mktime temp in let rem_date_str1 = (string_of_tm_mon tm1.Unix.tm_mon) ^ " " ^ (string_of_int tm1.Unix.tm_mday) ^ " " ^ (string_of_int (tm1.Unix.tm_year + 1900)) in let rem_date_str2 = (string_of_tm_mon tm2.Unix.tm_mon) ^ " " ^ (string_of_int tm2.Unix.tm_mday) ^ " " ^ (string_of_int (tm2.Unix.tm_year + 1900)) in let remind_output_for_month date_str = let remind_month_command = !Rcfile.remind_command ^ " -n -s -b1 " ^ !Rcfile.reminders_file ^ " " ^ date_str in let (out_lines, _) = Utility.read_all_shell_command_output remind_month_command in out_lines in (* concatenate the outputs from two consecutive months of Remind data, then sort * the lines by leading datestamp *) let two_month_output = List.rev_append (remind_output_for_month rem_date_str1) (remind_output_for_month rem_date_str2) in let out_lines = List.fast_sort compare two_month_output in let rec check_messages lines = begin match lines with | [] -> raise Occurrence_not_found | line :: lines_tail -> begin try if Str.string_match rem_regex line 0 then begin (* go here if this line is a timed reminder *) let year = int_of_string (Str.matched_group 1 line) and month = int_of_string (Str.matched_group 2 line) and day = int_of_string (Str.matched_group 3 line) and tag = Str.matched_group 4 line and min_s = Str.matched_group 5 line and msg = Str.matched_group 6 line in let temp = {empty_tm with Unix.tm_min = if min_s = "*" then 0 else (int_of_string min_s); Unix.tm_mday = day; Unix.tm_mon = pred month; Unix.tm_year = year - 1900; } in let (ts, _) = Unix.mktime temp in if ts > timestamp then begin try let _ = Str.search_forward msg_regex msg 0 in (* only return the match if this value is not tagged 'nodisplay' *) if not (Str.string_match nodisplay_regex tag 0) then ts else check_messages lines_tail with Not_found -> check_messages lines_tail end else begin check_messages lines_tail end end else (* if there was no regexp match, continue with next line *) check_messages lines_tail with | Failure s -> (* if there's an error in string coersion, just drop that reminder and go * to the next line *) check_messages lines_tail end end in check_messages out_lines (* Get a list of the main remfile and all INCLUDEd reminder files *) let get_included_remfiles () = let main_remfile = Utility.expand_file !Rcfile.reminders_file in let filedir = Filename.dirname main_remfile in let remfile_channel = open_in main_remfile in (* match "include " *) let include_regex = Str.regexp_case_fold "^[ \t]*include[ \t]+\\([^ \t]+.*\\)$" in (* match "[filedir()]" so we can do a Remind-like directory substitution *) let filedir_regex = Str.regexp_case_fold "\\[[ \t]*filedir[ \t]*([ \t]*)[ \t]*\\]" in let rec build_filelist files = try let line = input_line remfile_channel in if Str.string_match include_regex line 0 then let include_expr = Utility.strip (Str.matched_group 1 line) in let new_file = Str.global_replace filedir_regex filedir include_expr in build_filelist (new_file :: files) else build_filelist files with End_of_file -> close_in remfile_channel; List.rev files in build_filelist [main_remfile] (* Filter a list of untimed reminders, returning a list of those * reminders falling on the same day as the timestamp. *) let get_untimed_reminders_for_day untimed_reminders timestamp = let curr_tm = Unix.localtime timestamp in let temp1 = { curr_tm with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0 } in let temp2 = { curr_tm with Unix.tm_sec = 0; Unix.tm_min = 0; Unix.tm_hour = 0; Unix.tm_mday = succ curr_tm.Unix.tm_mday } in let (day_start_ts, _) = Unix.mktime temp1 in let (day_end_ts, _) = Unix.mktime temp2 in let is_current rem = rem.ur_start >= day_start_ts && rem.ur_start < day_end_ts in List.filter is_current untimed_reminders (* arch-tag: DO_NOT_CHANGE_6bb48a1c-2b0c-4254-ba3a-ee9b48007169 *) wyrd-1.4.4/locale.mli0000644000175000017500000000226210757447265013156 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) (* OCaml binding for setlocale(), required to kick ncurses into * properly rendering non-ASCII chars. *) type t = LC_ALL | LC_COLLATE | LC_CTYPE | LC_MONETARY | LC_NUMERIC | LC_TIME | LC_MESSAGES | LC_UNDEFINED of int external setlocale_int : int -> string -> string = "ml_setlocale" val setlocale : t -> string -> string wyrd-1.4.4/install.ml.in0000644000175000017500000000043310757447265013617 0ustar paulpaul(* Hard-code the installation prefix and sysconfdir. *) let prefix = "@prefix@";; let sysconfdir = "@sysconfdir@";; (* Did we compile with ncurses wide char support? *) let wide_ncurses = @BOOL_WIDE_CURSES@;; (* arch-tag: DO_NOT_CHANGE_b0af51b9-3cf0-479c-a33a-f9221e29ed48 *) wyrd-1.4.4/main.ml0000644000175000017500000000660010757447265012472 0ustar paulpaul(* Wyrd -- a curses-based front-end for Remind * Copyright (C) 2005, 2006, 2007 Paul Pelzl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please send bug reports, patches, etc. to Paul Pelzl at * . *) open Interface;; open Curses;; (* Load run configuration file *) Rcfile.process_rcfile None;; (* Parse command-line options *) let parse_anonymous_opt anon = Rcfile.reminders_file := anon in let usage = "Usage: wyrd [OPTIONS] [FILE]\n" ^ "Open a front-end to remind(1) using FILE as the reminders file.\n\nOPTIONS:" in let show_version () = print_endline ("Wyrd v" ^ Version.version); print_endline "Copyright (C) 2005, 2006, 2007 Paul Pelzl"; print_endline ""; print_endline "Wyrd comes with ABSOLUTELY NO WARRANTY. This is Free Software,"; print_endline "and you are welcome to redistribute it under certain conditions;"; print_endline "see the source code for details."; print_endline ""; exit 0; in let event_desc_opt = ref None in let do_quick_event event_desc = event_desc_opt := Some event_desc in let parse_definition = [ ("--version", Arg.Unit show_version, " Display version information and exit"); ("-a", Arg.String do_quick_event, " Add given event to reminders file and exit"); ("--add", Arg.String do_quick_event, " Add given event to reminders file and exit"); ] in Arg.parse (Arg.align parse_definition) parse_anonymous_opt usage; (* After parsing all arguments, handle quick reminders. We have to * do it in this order so that the filename (anonymous option) gets * set prior to creating the new event. *) begin match !event_desc_opt with | Some event_desc -> begin try let _ = Interface_main.append_quick_event event_desc !Rcfile.reminders_file in exit 0 with Time_lang.Event_parse_error s -> Printf.fprintf stderr "Error: %s\n" s; exit 1 end | None -> () end;; let initialize_screen () = if Install.wide_ncurses then (* ncursesw doesn't render non-ASCII without the setlocale() call *) let _ = Locale.setlocale Locale.LC_ALL "" in () else (); let std = initscr () in begin try assert (start_color ()); assert (use_default_colors ()); Rcfile.validate_colors () with _ -> endwin (); failwith "Your terminal emulator does not support color." end; assert (keypad std true); assert (cbreak ()); assert (halfdelay 100); assert (noecho ()); begin try assert (curs_set 0) with _ -> () end; Interface_main.create_windows std;; let iface = Interface.make (initialize_screen ());; try Interface_main.run iface with error -> endwin (); Printf.fprintf stderr "Caught error at toplevel:\n%s\n" (Printexc.to_string error);; (* arch-tag: DO_NOT_CHANGE_eeac13df-e93f-4359-8b70-44fefc40e225 *)