diff options
author | Rich Felker <dalias@aerifal.cx> | 2006-10-03 01:37:17 +0000 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2006-10-03 01:37:17 +0000 |
commit | 0fe28fd69dd15006ccd684d563699420aadde61a (patch) | |
tree | 77a419dc56462f39c975b6c043a7bf344fc3f3e6 |
first working version of uuterm!
- at this point it is purely experimental. only ascii characters are
visible (using builtin font) although all characters are processed.
- there are known bugs, including crashes.
- there are major missing features.
- but it works. ^_^
-rw-r--r-- | COPYING | 339 | ||||
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | alloc.c | 37 | ||||
-rw-r--r-- | ascii.c | 106 | ||||
-rw-r--r-- | comb.c | 196 | ||||
-rw-r--r-- | dblbuf.c | 220 | ||||
-rw-r--r-- | dblbuf.h | 29 | ||||
-rw-r--r-- | fbcon.c | 219 | ||||
-rw-r--r-- | main.c | 96 | ||||
-rw-r--r-- | refresh.c | 45 | ||||
-rw-r--r-- | term.c | 501 | ||||
-rw-r--r-- | tty.c | 63 | ||||
-rw-r--r-- | uuterm.h | 100 |
13 files changed, 1972 insertions, 0 deletions
@@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6dd74b2 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +# uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only + + +SRCS = main.c term.c comb.c tty.c alloc.c refresh.c ascii.c fbcon.c dblbuf.c +OBJS = $(SRCS:.c=.o) + +CFLAGS = -O2 -s #-g +LDFLAGS = -s + +-include config.mak + +all: uuterm + +$(OBJS): uuterm.h + +uuterm: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) + +clean: + rm -f $(OBJS) uuterm + @@ -0,0 +1,37 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <stdlib.h> +#include <sys/mman.h> + +#include "uuterm.h" + +void *uuterm_alloc(size_t len) +{ +#ifdef MAP_ANONYMOUS + size_t *mem = mmap(0, len+sizeof(size_t), + PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (mem == MAP_FAILED) return 0; + *mem++ = len; + return mem; +#else + return malloc(len); +#endif +} + +void uuterm_free(void *buf) +{ +#ifdef MAP_ANONYMOUS + size_t *mem = buf; + mem--; + munmap(mem, *mem); +#else + free(buf); +#endif +} + +void *uuterm_buf_alloc(int w, int h) +{ + /* FIXME: do we care about overflows? */ + return uuterm_alloc(UU_BUF_SIZE(w, h)); +} @@ -0,0 +1,106 @@ +/* Standard ASCII console font. If you want to pretend there's a copyright + * on this you'll just be making a fool of yourself. Public domain. */ + +static const unsigned char ascii[] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x10,0x10,0x7c,0xd6,0xd0,0xd0,0x7c,0x16,0x16,0xd6,0x7c,0x10,0x10,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xce,0xce,0xd6,0xd6,0xe6,0xe6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x64,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x7e,0x5a,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0xee,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0x6c,0x7c,0x38,0x38,0x7c,0x6c,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x86,0x0c,0x18,0x30,0x60,0xc2,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc0,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, +0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xec,0xfe,0xd6,0xd6,0xd6,0xd6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0x6c,0x38,0x38,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +const void *ascii_get_glyph(unsigned c) +{ + if (c - 32 < 95) return ascii + 16*(c-32); + else return ascii; +} @@ -0,0 +1,196 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#define R(a,b) { (a), (b)-(a) } + +static const unsigned short common[][2] = { + R( 0x300, 0x341 ), + R( 0x346, 0x362 ), + R( 0x200B, 0x200F ), + R( 0x202A, 0x202E ), + R( 0x2060, 0x206F ), + R( 0x20D0, 0x20EA ), + { 0, 0 } +}; + +static const unsigned short latin[][2] = { + R( 0x363, 0x36F ), + { 0, 0 } +}; + +static const unsigned short greek[][2] = { + R( 0x342, 0x345 ), + { 0, 0 } +}; + +static const unsigned short cyrillic[][2] = { + R( 0x483, 0x489 ), + { 0, 0 } +}; + +static const unsigned short hebrew[][2] = { + R( 0x591, 0x5C4 ), + { 0, 0 } +}; + +static const unsigned short arabic[][2] = { + R( 0x600, 0x603 ), + R( 0x610, 0x615 ), + R( 0x64B, 0x658 ), + R( 0x670, 0x670 ), + R( 0x6D6, 0x6ED ), + { 0, 0 } +}; + +static const unsigned short syriac[][2] = { + R( 0x70F, 0x711 ), + R( 0x730, 0x74A ), + { 0, 0 } +}; + +static const unsigned short thaana[][2] = { + R( 0x7A6, 0x7B0 ), + { 0, 0 } +}; + +static const unsigned short devanagari[][2] = { + R( 0x901, 0x902 ), + R( 0x93C, 0x963 ), + { 0, 0 } +}; + +static const unsigned short bengali[][2] = { + R( 0x981, 0x981 ), + R( 0x9BC, 0x9E3 ), + { 0, 0 } +}; + +static const unsigned short gurmukhi[][2] = { + R( 0xA01, 0xA02 ), + R( 0xA3C, 0xA4D ), + R( 0xA70, 0xA71 ), + { 0, 0 } +}; + +static const unsigned short gujarati[][2] = { + R( 0xA81, 0xA82 ), + R( 0xABC, 0xAE3 ), + { 0, 0 } +}; + +static const unsigned short oriya[][2] = { + R( 0xB01, 0xB01 ), + R( 0xB3C, 0xB4D ), + R( 0xB56, 0xB56 ), + { 0, 0 } +}; + +static const unsigned short tamil[][2] = { + R( 0xB82, 0xB82 ), + R( 0xBC0, 0xBCD ), + { 0, 0 } +}; + +static const unsigned short telugu[][2] = { + R( 0xC3E, 0xC56 ), + { 0, 0 } +}; + +static const unsigned short kannada[][2] = { + R( 0xCBC, 0xCCD ), + { 0, 0 } +}; + +static const unsigned short malayalam[][2] = { + R( 0xD41, 0xD4D ), + { 0, 0 } +}; + +static const unsigned short sinhala[][2] = { + R( 0xDCA, 0xDD6 ), + { 0, 0 } +}; + +static const unsigned short thai[][2] = { + R( 0xE31, 0xE3A ), + R( 0xE47, 0xE4E ), + { 0, 0 } +}; + +static const unsigned short lao[][2] = { + R( 0xEB1, 0xECD ), + { 0, 0 } +}; + +static const unsigned short tibetan[][2] = { + R( 0xF18, 0xF19 ), + R( 0xF35, 0xF35 ), + R( 0xF39, 0xF39 ), + R( 0xF71, 0xF84 ), + R( 0xF90, 0xFBC ), + R( 0xFC6, 0xFC6 ), + { 0, 0 } +}; + +static const unsigned short burmese[][2] = { + R( 0x102D, 0x1039 ), + R( 0x1058, 0x1059 ), + { 0, 0 } +}; + +static const unsigned short misc_scripts[][2] = { + R( 0x1732, 0x1734 ), /* hanunoo */ + R( 0x1752, 0x1753 ), /* buhid */ + R( 0x17B4, 0x17BD ), /* khmer */ + R( 0x17C6, 0x17D3 ), + R( 0x17DD, 0x17DD ), + R( 0x18A9, 0x18A9 ), /* mongolian */ + R( 0x1920, 0x193B ), /* limbu (can be broken down more) */ + { 0, 0 } +}; + +#undef R +#define R(a,b,s) { (a), (b)-(a), (s) } + +static const struct { + unsigned a, l; + const unsigned short (*r)[2]; +} scripts[] = { + R( 0x400, 0x52F, cyrillic ), + R( 0x590, 0x5FF, hebrew ), + R( 0x600, 0x6FF, arabic ), + R( 0x700, 0x74F, syriac ), + R( 0x780, 0x7B1, thaana ), + R( 0x900, 0x97F, devanagari ), + R( 0x980, 0x9FF, bengali ), + R( 0xA00, 0xA7F, gurmukhi ), + R( 0xA80, 0xAFF, gujarati ), + R( 0xB00, 0xB7F, oriya ), + R( 0xB80, 0xBFF, tamil ), + R( 0xC00, 0xC7F, telugu ), + R( 0xC80, 0xCFF, kannada ), + R( 0xD00, 0xD7F, malayalam ), + R( 0xD80, 0xDFF, sinhala ), + R( 0xF00, 0xFFF, tibetan ), + R( 0x1000, 0x108F, burmese ), + R( 0x1720, 0x19FF, misc_scripts ), + R( 0x1D2B, 0x1D2B, cyrillic ), + R( 0x0000, 0x10FFFF, common ), + { } +}; + +#undef R + +int uu_combine_involution(unsigned b, unsigned c) +{ + int i; + unsigned code = 1; + const unsigned short (*r)[2]; + for (i=0; scripts[i].l; i++) + if (b - scripts[i].a <= scripts[i].l) + for (r = scripts[i].r; r[0][0]; code += r++[0][1]) + if (c - r[0][0] <= r[0][1]) + return c - r[0][0] + code; + else if (c - code <= r[0][1]) + return c + r[0][0] - code; + return 0; +} diff --git a/dblbuf.c b/dblbuf.c new file mode 100644 index 0000000..ad70576 --- /dev/null +++ b/dblbuf.c @@ -0,0 +1,220 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include "uuterm.h" +#include "dblbuf.h" + +#if 0 +static void blitline8_crap(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw) +{ + int cs = (cw+7)>>3; + int skip = (-cw)&7; + int x, i, j; + signed char b; + for (x=0; x<w; x++) { + j=skip; + b=*src++<<skip; + for (i=0; ; i++) { + for (; j<8; j++, b<<=1) + //*dest++ = 7 & (b>>7); + *dest++ = (*colors&15&(b>>7)) | (*colors>>4&~(b>>7)); + if (i >= cs) break; + b=*src++; + j=0; + } + colors++; + } +} + +static void blitline8_2(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw) +{ + int cs = (cw+7)>>3; + int skip = (-cw)&7; + int x, i, j; + signed char b; + unsigned char fg, bg; + + for (x=0; x<w; x++) { + j=skip; + b=*src++<<skip; + fg = *colors & 15; + bg = *colors++ >> 4; + for (i=0; ; i++) { + for (; j<8; j++, b<<=1) + *dest++ = (fg&(b>>7)) | (bg&~(b>>7)); + if (i >= cs) break; + b=*src++; + j=0; + } + } +} +#endif + +#ifdef HAVE_I386_ASM + +#define BLIT_PIXEL_8 \ + "add %%al,%%al \n\t" \ + "sbb %%dl,%%dl \n\t" \ + "and %%bh,%%dl \n\t" \ + "mov %%bl,%%dh \n\t" \ + "add %%dl,%%dh \n\t" \ + "mov %%dh,(%%edi) \n\t" \ + "inc %%edi \n\t" \ + +static void blitline8(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw) +{ + __asm__ __volatile__( + "push %%ebp \n\t" + "mov %%ebx, %%ebp \n\t" + "\n1: \n\t" + "mov (%%esi), %%al \n\t" + "inc %%esi \n\t" + "mov (%%ecx), %%bl \n\t" + "inc %%ecx \n\t" + "mov %%bl, %%bh \n\t" + "shr $4, %%bl \n\t" + "and $15, %%bh \n\t" + "sub %%bl, %%bh \n\t" + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + BLIT_PIXEL_8 + "dec %%ebp \n\t" + "jnz 1b \n\t" + "pop %%ebp \n\t" + : "=S"(src), "=D"(dest), "=c"(colors), "=b"(w) + : "S"(src), "D"(dest), "c"(colors), "b"(w) + : "memory" ); +} +#else +static void blitline8(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw) +{ + int x; + unsigned char b; + unsigned char c[2]; + + for (x=0; x<w; x++) { + b=*src++; + c[1] = *colors & 15; + c[0] = *colors++ >> 4; + dest[0] = c[b>>7]; b<<=1; + dest[1] = c[b>>7]; b<<=1; + dest[2] = c[b>>7]; b<<=1; + dest[3] = c[b>>7]; b<<=1; + dest[4] = c[b>>7]; b<<=1; + dest[5] = c[b>>7]; b<<=1; + dest[6] = c[b>>7]; b<<=1; + dest[7] = c[b>>7]; b<<=1; + dest += 8; + } +} +#endif + +static void blit_slice(struct uudisp *d, int idx, int x1, int x2) +{ + struct dblbuf *b = (void *)&d->priv; + int cs = (d->cell_w+7)>>3; + int y = b->slices[idx].y; + int w = x2 - x1 + 1; + int s = d->w * cs; + int i; + + unsigned char *dest = b->vidmem + y*b->row_stride + + x1*d->cell_w*b->bytes_per_pixel; + unsigned char *src = b->slices[idx].bitmap + x1*cs; + unsigned char *colors = b->slices[idx].colors + x1; + + for (i=0; i<d->cell_h; i++) { + blitline8(dest, src, colors, w, d->cell_w); + dest += b->line_stride; + src += s; + } +} + +void clear_cells(struct uudisp *d, int idx, int x1, int x2) +{ + struct dblbuf *b = (void *)&d->priv; + int i; + int cs = d->cell_w+7 >> 3; + int cnt = (x2 - x1 + 1) * cs; + int stride = d->w * cs; + unsigned char *dest = b->slices[idx].bitmap + x1 * cs; + + memset(b->slices[idx].colors + x1, 0, x2-x1+1); + for (i=d->cell_h; i; i--, dest += stride) + memset(dest, 0, cnt); +} + +void uudisp_draw_glyph(struct uudisp *d, int idx, int x, const void *glyph, int color) +{ + struct dblbuf *b = (void *)&d->priv; + int i; + int cs = d->cell_w+7 >> 3; + int stride = d->w * cs; + unsigned char *src = (void *)glyph; + unsigned char *dest = b->slices[idx].bitmap + cs * x; + + b->slices[idx].colors[x] = color; + for (i=d->cell_h; i; i--, dest += stride) + *dest |= *src++; +} + +void uudisp_refresh(struct uudisp *d, struct uuterm *t) +{ + struct dblbuf *b = (void *)&d->priv; + int h = t->h < d->h ? t->h : d->h; + int y; + + /* Clean up cursor first.. */ + blit_slice(d, t->rows[b->curs_y]->idx, b->curs_x, b->curs_x); + //printf("--- %d\r\n", b->slices[t->rows[b->curs_y]->idx].y); + + for (y=0; y<h; y++) { + int idx = t->rows[y]->idx; + int x1 = t->rows[y]->x1; + int x2 = t->rows[y]->x2; + if (x2 >= x1) { + clear_cells(d, idx, x1, x2); + uuterm_refresh_row(d, t->rows[y], x1, x2); + t->rows[y]->x1 = t->w; + t->rows[y]->x2 = -1; + } + if (b->slices[idx].y != y) { + b->slices[idx].y = y; + x1 = 0; + x2 = d->w-1; + } else if (x2 < x1) continue; + blit_slice(d, idx, x1, x2); + } + + if (d->blink & 1) { + int idx = t->rows[t->y]->idx; + b->slices[idx].colors[t->x] ^= 0xff; + blit_slice(d, idx, t->x, t->x); + b->slices[idx].colors[t->x] ^= 0xff; + } + b->curs_x = t->x; + b->curs_y = t->y; + //printf("+++ %d\r\n", b->slices[t->rows[b->curs_y]->idx].y); +} + +struct slice *dblbuf_setup_buf(int w, int h, int cs, int ch, unsigned char *mem) +{ + struct slice *slices = (void *)mem; + int i; + + mem += sizeof(slices[0]) * h; + + for (i=0; i<h; i++, mem += w) { + slices[i].y = -1; + slices[i].colors = mem; + } + w *= cs * ch; + for (i=0; i<h; i++, mem += w) + slices[i].bitmap = mem; + + return slices; +} diff --git a/dblbuf.h b/dblbuf.h new file mode 100644 index 0000000..aa2dc47 --- /dev/null +++ b/dblbuf.h @@ -0,0 +1,29 @@ + + + +struct slice +{ + int y; + unsigned char *colors; + unsigned char *bitmap; +}; + +struct dblbuf +{ + struct slice *slices; + unsigned cs, ch; + + unsigned curs_x; + unsigned curs_y; + + unsigned char *vidmem; + unsigned row_stride; + unsigned line_stride; + unsigned bytes_per_pixel; +}; + +#define SLICE_BUF_SIZE(w, h, cs, ch) \ + ( (h)*(sizeof(struct slice) + (w)*(1 + (cs)*(ch))) ) + +struct slice *dblbuf_setup_buf(int, int, int, int, unsigned char *); + @@ -0,0 +1,219 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <unistd.h> +#include <fcntl.h> +#include <sys/select.h> +#include <signal.h> +#include <termios.h> +#include <sys/mman.h> +#include <sys/ioctl.h> + +#include <sys/kd.h> +#include <linux/fb.h> + +#include "uuterm.h" +#include "dblbuf.h" + +struct priv +{ + /* common to all double buffered fb targets */ + struct dblbuf b; + /* fbcon-specific */ + int fb; + int kb; + int ms; + struct termios tio; + int kbmode; + int mod; + int xres, yres; + void *buf_mem; +}; + +static int get_fb_size(struct uudisp *d) +{ + struct priv *p = (struct priv *)&d->priv; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + + if (ioctl(p->fb, FBIOGET_FSCREENINFO, &fix) < 0 + || ioctl(p->fb, FBIOGET_VSCREENINFO, &var) < 0 + || fix.type != FB_TYPE_PACKED_PIXELS) + return -1; + + p->b.bytes_per_pixel = (var.bits_per_pixel+7)>>3; + p->b.line_stride = fix.line_length; + p->b.row_stride = fix.line_length * d->cell_h; + + if (var.xres != p->xres || var.yres != p->yres) { + int w = var.xres / d->cell_w; + int h = var.yres / d->cell_h; + void *buf = uuterm_alloc(SLICE_BUF_SIZE(w, h, (d->cell_w+7)/8, d->cell_h)); + if (!buf) return -1; + if (p->buf_mem) uuterm_free(p->buf_mem); + p->buf_mem = buf; + p->b.slices = dblbuf_setup_buf(w, h, (d->cell_w+7)/8, d->cell_h, buf); + p->xres = var.xres; + p->yres = var.yres; + d->w = w; + d->h = h; + } + + return 0; +} + +static void dummy(int x) +{ +} + +static int mapkey(unsigned *m, unsigned k, unsigned char *s) +{ +#define LSHIFT "\200" +#define LCTRL "\201" +#define LALT "\202" +#define RSHIFT "\203" +#define RCTRL "\204" +#define RALT "\205" +#define CAPSLK "\206" +#define NUMLK "\207" +#define SCRLK "\210" +#define WTF "\377" + static const unsigned char keymap[] = + "\0\033" "1234567890-=\177" + "\t" "qwertyuiop[]\r" + LCTRL "asdfghjkl;'`" + LSHIFT "\\zxcvbnm,./" RSHIFT "*" + LALT " " CAPSLK + "\301\302\303\304\305\306\307\310\311\312" + NUMLK SCRLK; + static const unsigned char keymap_sh[] = + "\0\033" "!@#$%^&*()_+\177" + "\t" "QWERTYUIOP{}\r" + LCTRL "ASDFGHJKL:\"~" + LSHIFT "|ZXCVBNM<>?" RSHIFT "*" + LALT " " CAPSLK + "\301\302\303\304\305\306\307\310\311\312" + NUMLK SCRLK; + //71... + static const unsigned char keypad[] = "789-456+1230."; + //64..95 useless + //96... + static const unsigned char keypad2[] = "\r" RCTRL WTF "/" RALT WTF; + //102... + static const unsigned char cursblk[] = "1A5DC4B623"; + + unsigned c; + unsigned rel = k & 0x80; + int i = 0; + + k &= 0x7f; + if (k < sizeof(keymap)) { + c = keymap[k]; + if (c-0200 < 6) { + c &= 15; + if (rel) *m &= ~(1<<c); + else *m |= 1<<c; + return 0; + } + if (rel || c > 0x80) return 0; + if (*m & 1) c = keymap_sh[k]; + if (*m & 2) { + c &= 0x1f; + //if (c >= '@') c &= 0x1f; + //else if (keymap_sh[k] >= '@') c = keymap_sh[k] & 0x1f; + } + if (*m & 4) { + s[i++] = '\033'; + } + s[i++] = c; + return i; + } + if (k-102 < sizeof(cursblk)) { + if (rel) return 0; + s[i++] = '\033'; + s[i++] = '['; + c = cursblk[k-102]; + s[i++] = c; + if (c < 'A') s[i++] = '~'; + return i; + } + return 0; +} + +int uudisp_open(struct uudisp *d) +{ + struct priv *p = (void *)&d->priv; + struct fb_fix_screeninfo fix; + struct termios tio; + + p->fb = p->kb = p->ms = -1; + p->b.vidmem = MAP_FAILED; + + if ((p->fb = open("/dev/fb0", O_RDWR)) < 0 || get_fb_size(d) < 0 + || ioctl(p->fb, FBIOGET_FSCREENINFO, &fix) < 0) + goto error; + + p->b.vidmem = mmap(0, fix.smem_len, PROT_WRITE|PROT_READ, MAP_SHARED, p->fb, 0); + if (p->b.vidmem == MAP_FAILED) + goto error; + + if ((p->kb = open("/dev/tty", O_RDONLY)) < 0 + || ioctl(p->kb, KDGKBMODE, &p->kbmode) < 0 + || ioctl(p->kb, KDSKBMODE, K_MEDIUMRAW) < 0) + goto error; + + /* If the above succeeds, the below cannot fail */ + ioctl(p->kb, KDSETMODE, KD_GRAPHICS); + tcgetattr(p->kb, &p->tio); + tio = p->tio; + tio.c_cflag = B38400 | CS8 | CLOCAL | CREAD; + tio.c_iflag = 0; + tio.c_oflag = 0; + tio.c_lflag = 0; + tcsetattr(p->kb, TCSANOW, &tio); + + signal(SIGWINCH, dummy); /* just to interrupt select! */ + signal(SIGTSTP, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + + return 0; +error: + if (p->b.vidmem != MAP_FAILED) munmap(p->b.vidmem, fix.smem_len); + close(p->fb); + close(p->kb); + close(p->ms); + return -1; +} + +int uudisp_fd_set(struct uudisp *d, int tty, void *fds) +{ + struct priv *p = (struct priv *)&d->priv; + if (p->ms >= 0) FD_SET(p->ms, (fd_set *)fds); + FD_SET(p->kb, (fd_set *)fds); + return p->kb > tty ? p->kb+1 : tty+1; +} + +void uudisp_next_event(struct uudisp *d, void *fds) +{ + struct priv *p = (struct priv *)&d->priv; + unsigned char b; + + get_fb_size(d); + + d->inlen = 0; + d->intext = d->inbuf; + + if (FD_ISSET(p->kb, (fd_set *)fds) && read(p->kb, &b, 1) == 1) + d->inlen = mapkey(&p->mod, b, d->intext); +} + +void uudisp_close(struct uudisp *d) +{ + struct priv *p = (struct priv *)&d->priv; + tcsetattr(p->kb, TCSANOW, &p->tio); + ioctl(p->kb, KDSKBMODE, p->kbmode); + ioctl(p->kb, KDSETMODE, KD_TEXT); + close(p->fb); + close(p->kb); + close(p->ms); +} @@ -0,0 +1,96 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <locale.h> +#include <sys/select.h> +#include <sys/time.h> /* for broken systems */ + +#include "uuterm.h" + +int main(int argc, char *argv[]) +{ + struct uuterm t = { }; + struct uudisp d = { }; + int tty, max; + int i, l; + unsigned char b[128]; + fd_set fds; + struct timeval tv; + void *buf; + + setlocale(LC_CTYPE, ""); + + d.cell_w = 8; + d.cell_h = 16; + + if (uudisp_open(&d) < 0) + return 1; + + for (i=1; i<argc; i++) + argv[i-1] = argv[i]; + argv[i-1] = NULL; + + if ((tty = uutty_open(argc > 1 ? argv : NULL, d.w, d.h)) < 0) + return 1; + + signal(SIGHUP, SIG_IGN); + + if (!(buf = uuterm_buf_alloc(d.w, d.h))) { + uudisp_close(&d); + return 1; + } + uuterm_replace_buffer(&t, d.w, d.h, buf); + uuterm_reset(&t); + + for (;;) { + /* Setup fd_set containing fd's used by display and our tty */ + FD_ZERO(&fds); + FD_SET(tty, &fds); + max = uudisp_fd_set(&d, tty, &fds); + tv.tv_sec = 0; + tv.tv_usec = 250000; + if (select(max, &fds, NULL, NULL, &tv) == 0) + d.blink++; + + /* Process input from the tty, up to buffer size */ + if (FD_ISSET(tty, &fds)) { + if ((l = read(tty, b, sizeof b)) <= 0) + break; + for (i=0; i<l; i++) { + uuterm_stuff_byte(&t, b[i]); + if (t.reslen) write(tty, t.res, t.reslen); + } + } + + /* Look for events from the display */ + uudisp_next_event(&d, &fds); + + if (d.w != t.w || d.h != t.h) { + void *newbuf = uuterm_buf_alloc(d.w, d.h); + if (newbuf) { + uuterm_replace_buffer(&t, d.w, d.h, newbuf); + uuterm_free(buf); + buf = newbuf; + uutty_resize(tty, d.w, d.h); + } + } + if (d.inlen) { + write(tty, d.intext, d.inlen); + d.blink = 1; + } + + /* If no more input is pending, refresh display */ + FD_ZERO(&fds); + FD_SET(tty, &fds); + tv.tv_sec = tv.tv_usec = 0; + select(max, &fds, NULL, NULL, &tv); + if (!FD_ISSET(tty, &fds)) + uudisp_refresh(&d, &t); + } + + uudisp_close(&d); + + return 0; +} diff --git a/refresh.c b/refresh.c new file mode 100644 index 0000000..b1766d2 --- /dev/null +++ b/refresh.c @@ -0,0 +1,45 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include "uuterm.h" + +static void extract_cell(unsigned *ch, struct uucell *cell) +{ + int i; + unsigned b; + for (b=i=0; i<3; i++) b |= cell->c[i] << 8*i; + ch[0] = b; + ch -= 2; + for (; i<sizeof(cell->c)+1 && cell->c[i]; i++) + ch[i] = uu_combine_involution(b, cell->c[i]); + if (cell->a & UU_ATTR_UL) + ch[i++] = '_'; //0x0332; + for (; i<sizeof(cell->c)+1; i++) + ch[i] = 0; +} + +const void *ascii_get_glyph(unsigned); + +static const void *lookup_glyph(unsigned *this, int i, unsigned *prev, unsigned *next) +{ + return ascii_get_glyph(this[i]); +} + +void uuterm_refresh_row(struct uudisp *d, struct uurow *row, int x1, int x2) +{ + unsigned ch[4][sizeof(row->cells[0].c)+1]; + int x, i; + + if (x1) extract_cell(ch[(x1-1)&3], &row->cells[x1-1]); + else memset(ch[3], 0, sizeof(ch[3])); + extract_cell(ch[x1&3], &row->cells[x1]); + + for (x=x1; x<=x2; x++) { + extract_cell(ch[(x+1)&3], &row->cells[x+1]); + for (i=0; i<sizeof(ch[0]) && ch[x&3][i]; i++) { + const void *glyph = lookup_glyph(ch[x&3], i, ch[(x+3)&3], ch[(x+1)&3]); + uudisp_draw_glyph(d, row->idx, x, glyph, row->cells[x].a); + } + } +} + + @@ -0,0 +1,501 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <wchar.h> +#include <stdint.h> +#include <stddef.h> +#include <string.h> +#include "uuterm.h" + +#define isdigit(x) ((unsigned)x-'0' < 10) + +static void process_char(struct uuterm *t, unsigned c); + +static void scroll(struct uuterm *t, int y1, int y2, int rev) +{ + int fwd = 1-rev; + struct uurow *new = t->rows[(y1&-fwd)|(y2&-rev)]; + memset(new->cells, 0, t->w * sizeof(struct uucell)); + new->x1 = 0; + new->x2 = t->w-1; + memmove(&t->rows[y1+rev], &t->rows[y1+fwd], (y2-y1) * sizeof(struct uurow *)); + t->rows[(y2&-fwd)|(y1&-rev)] = new; +} + +static void dirty(struct uuterm *t, int y, int x1, int len) +{ + int x2 = x1 + len - 1; + struct uurow *r = t->rows[y]; + //r->x1 += (x1 - r->x1) & (x1 - r->x1)>>8*sizeof(int)-1; + //r->x2 += (x2 - r->x2) & (r->x2 - x2)>>8*sizeof(int)-1; + if (x1 < r->x1) r->x1 = x1; + if (x2 > r->x2) r->x2 = x2; +} + +static void bell(struct uuterm *t) +{ +} + +static void erase_line(struct uuterm *t, int dir) +{ + int start[3] = { t->x, 0, 0 }; + int len[3] = { t->w-t->x, t->x+1, t->w }; + if ((unsigned)dir > 2) return; + memset(t->rows[t->y]->cells+start[dir], 0, len[dir] * sizeof(struct uucell)); + dirty(t, t->y, start[dir], len[dir]); +} + +static void erase_display(struct uuterm *t, int dir) +{ + int i; + int start[3] = { t->y+1, 0, 0 }; + int stop[3] = { t->h, t->y, t->h }; + if ((unsigned)dir > 2) return; + erase_line(t, dir); + for (i=start[dir]; i<stop[dir]; i++) { + memset(t->rows[i]->cells, 0, t->w * sizeof(struct uucell)); + dirty(t, i, 0, t->w); + } +} + +static void reset(struct uuterm *t) +{ + /* cheap trick */ + memset(&t->reset, 0, sizeof *t - offsetof(struct uuterm, reset)); + t->attr = 7; + t->sr_y2 = t->h - 1; + erase_display(t, 2); +} + +static void ins_del_char(struct uuterm *t, unsigned n, int ins) +{ + int del = 1-ins; + struct uucell *base; + if (n >= t->w - t->x) { + erase_line(t, 0); + return; + } + base = t->rows[t->y]->cells + t->x; + memmove(base+(n&-ins), base+(n&-del), (t->w-t->x-n) * sizeof(struct uucell)); + memset(base+((t->w-t->x-n)&-del), 0, n * sizeof(struct uucell)); + dirty(t, t->y, t->x, t->w - t->x); +} + +static void ins_del_lines(struct uuterm *t, int n, int ins) +{ + if ((unsigned)t->y - t->sr_y1 > t->sr_y2 - t->sr_y1) return; + while (n--) scroll(t, t->y, t->sr_y2, ins); +} + +static void newline(struct uuterm *t) +{ + process_char(t, '\r'); + process_char(t, '\n'); +} + +static int itoa(char *s, unsigned n) +{ + // FIXME!! + *s = '1'; + return 1; +} + +#define CSI '[' +#define OSC ']' +#define IGNORE1 2 +#define ID_STRING "\033[?6c" +#define OK_STRING "\033[0n" +#define PRIVATE ((unsigned)-1) + +static void csi(struct uuterm *t, unsigned c) +{ + int i; + int ins=0; + if (c == '?') { + t->param[t->nparam] = PRIVATE; + if (++t->nparam != 16) return; + } + if (isdigit(c)) { + t->param[t->nparam] = 10*t->param[t->nparam] + c - '0'; + return; + } + if (c == ';' && ++t->nparam != 16) + return; + t->esc = 0; + t->nparam++; + if (strchr("@ABCDEFGHLMPXaefr`", c) && !t->param[0]) + t->param[0]++; + switch (c) { + case 'F': + process_char(t, '\r'); + case 'A': + t->y -= t->param[0]; + break; + case 'E': + process_char(t, '\r'); + case 'e': + case 'B': + t->y += t->param[0]; + break; + case 'a': + case 'C': + t->x += t->param[0]; + break; + case 'D': + t->x -= t->param[0]; + break; + case '`': + case 'G': + t->x = t->param[0]-1; + break; + case 'f': + case 'H': + if (!t->param[1]) t->param[1]++; + t->y = t->param[0]-1; + t->x = t->param[1]-1; + break; + case 'J': + erase_display(t, t->param[0]); + break; + case 'K': + erase_line(t, t->param[0]); + break; + case 'L': + ins=1; + case 'M': + ins_del_lines(t, t->param[0], ins); + break; + case '@': + ins=1; + case 'P': + ins_del_char(t, t->param[0], ins); + break; + case 'd': + t->y = t->param[0]-1; + break; + case 'h': + case 'l': + i = c=='h'; + switch (t->param[0]) { + case PRIVATE: + switch(t->param[1]) { + case 1: + t->ckp = i; + break; + } + break; + case 4: + t->ins = i; + break; + } + break; + case 'm': + for (i=0; i<t->nparam; i++) { + static const unsigned char cmap[] = { + 0, 4, 2, 6, 1, 5, 3, 7 + }; + static const unsigned short attr[] = { + UU_ATTR_BOLD, UU_ATTR_DIM, 0, + UU_ATTR_UL, UU_ATTR_BLINK, 0, + UU_ATTR_REV + }; + if (t->param[i] == 39) t->param[i] = 37; + if (t->param[i] == 49) t->param[i] = 40; + if (!t->param[i]) { + t->attr = 7; + } else if (t->param[i] < 8) { + t->attr |= attr[t->param[i]-1]; + } else if (t->param[i]-21 < 7) { + t->attr &= ~attr[t->param[i]-21]; + } else if (t->param[i]-30 < 8) { + t->attr &= ~UU_ATTR_FG; + t->attr |= cmap[(t->param[i] - 30)]; + } else if (t->param[i]-40 < 8) { + t->attr &= ~UU_ATTR_BG; + t->attr |= cmap[(t->param[i] - 40)] << 4; + } + } + break; + case 'n': + switch (t->param[0]) { + case 5: + strcpy(t->res, OK_STRING); + t->reslen = sizeof(OK_STRING)-1; + break; + case 6: + t->res[0] = 033; + t->res[1] = '['; + i=2+itoa(t->res+2, t->x+1); + t->res[i++] = ';'; + i+=itoa(t->res+i, t->y+1); + t->res[i++] = 'R'; + t->reslen = i; + break; + } + break; + case 'r': + if (!t->param[1]) t->param[1] = t->h; + t->sr_y1 = t->param[0]-1; + t->sr_y2 = t->param[1]-1; + if (t->sr_y1 < 0) t->sr_y1 = 0; + if (t->sr_y2 >= t->h) t->sr_y2 = t->h-1; + if (t->sr_y1 > t->sr_y2) { + t->sr_y1 = 0; + t->sr_y2 = t->h-1; + } + break; + case 's': + t->save_x = t->x; + t->save_y = t->y; + break; + case 'u': + t->x = t->save_x; + t->y = t->save_y; + break; + case '[': + t->esc = IGNORE1; + break; + } + if ((unsigned)t->y >= t->h) { + if (t->y < 0) t->y = 0; + else t->y = t->h-1; + } + if ((unsigned)t->x >= t->w) { + if (t->x < 0) t->x = 0; + else t->x = t->w-1; + } +} + +static void escape(struct uuterm *t, unsigned c) +{ + int rev=0; + if ((c & ~2) == 030) { + t->esc = 0; + return; + } + if (t->esc == CSI) { + csi(t, c); + return; + } else if (t->esc == OSC) { + //FIXME + t->esc = 0; + return; + } else if (t->esc == IGNORE1) { + t->esc = 0; + return; + } + t->esc = 0; + switch (c) { + case 'c': + reset(t); + break; + case 'D': + process_char(t, '\n'); + break; + case 'E': + newline(t); + break; + case 'M': + if (t->y == t->sr_y1) scroll(t, t->sr_y1, t->sr_y2, 1); + else if (t->y > 0) t->y--; + break; + case 'Z': + strcpy(t->res, ID_STRING); + t->reslen = sizeof(ID_STRING)-1; + break; + case '7': + t->save_attr = t->attr; + t->save_x = t->x; + t->save_y = t->y; + break; + case '8': + t->attr = t->save_attr; + t->x = t->save_x; + t->y = t->save_y; + break; + case '[': + t->esc = CSI; + t->nparam = 0; + memset(t->param, 0, sizeof t->param); + break; + case '>': + t->kp = 0; + break; + case '=': + t->kp = 1; + break; + case ']': + t->esc = OSC; + t->nparam = 0; + memset(t->param, 0, sizeof t->param); + break; + } +} + +static void setchar(struct uucell *cell, unsigned c, unsigned a) +{ + int i; + if (a & UU_ATTR_REV) + cell->a = (a & ~(0xff)) + | ((a & 0x0f) << 4) + | ((a & 0xf0) >> 4); + else + cell->a = a; + for (i=0; i<sizeof(cell->c); i++, c>>=8) + cell->c[i] = c; +} + +static void addchar(struct uucell *cell, unsigned c) +{ + int i; + unsigned b; + + for (i=b=0; i<3; i++) b |= cell->c[i] << 8*i; + if (b == 0 || b == ' ' || b == 0xa0) { + setchar(cell, c, cell->a); + return; + } + if (!(c = uu_combine_involution(b, c))) return; + for (; i<sizeof(cell->c); i++) { + if (!cell->c[i]) { + cell->c[i] = c; + break; + } + } +} + +static void process_char(struct uuterm *t, unsigned c) +{ + int x, y, w; + t->reslen = 0; // default no response + if (c - 0x80 < 0x20) { + /* C1 control codes */ + process_char(t, 033); + process_char(t, c-0x40); + return; + } + if (t->esc) { + escape(t, c); + return; + } + switch(w=wcwidth(c)) { + case -1: + switch (c) { + case 033: + t->esc = 1; + break; + case '\r': + t->x = 0; + break; + case '\n': + if (t->y == t->sr_y2) scroll(t, t->sr_y1, t->sr_y2, 0); + else if (t->y < t->h-1) t->y++; + break; + case '\t': + t->x = (t->x + 8) & ~7; + if (t->x >= t->w) t->x = t->w - 1; + break; + case '\b': + if (!t->am && t->x) t->x--; + break; + case '\a': + bell(t); + break; + default: + process_char(t, 0xfffd); + break; + } + t->am = 0; + break; + case 0: + y = t->y; + x = t->x; + if (!x--) { + /* nothing to combine at home position */ + if (!y--) return; + x = 0; + } + + addchar(&t->rows[y]->cells[x], c); + dirty(t, y, x, 1); + break; + case 1: + case 2: + if (t->ins) ins_del_char(t, w, 1); + while (w--) { + if (t->am) newline(t); // kills am flag + dirty(t, t->y, t->x, 1); + setchar(&t->rows[t->y]->cells[t->x++], w?UU_FULLWIDTH:c, t->attr); + if (t->x == t->w) { + t->x--; + t->am=1; + } + } + break; + } +} + +#define BAD_CHAR 0xffff + +void uuterm_stuff_byte(struct uuterm *t, unsigned char b) +{ + int i, l; + wchar_t wc; + mbstate_t init_mbs = { }; + + for (i=0; i<2; i++) { + l = mbrtowc(&wc, &b, 1, &t->mbs); + if (l >= 0) { + if (wc) process_char(t, wc); + return; + } else if (l == -2) return; + + if (!i) process_char(t, BAD_CHAR); + t->mbs = init_mbs; + } +} + +void uuterm_replace_buffer(struct uuterm *t, int w, int h, void *buf) +{ + int i; + char *p = buf; + struct uurow **rows; + int wmin = w < t->w ? w : t->w; + + // keep the cursor on the screen after resizing + if (t->y >= h) { + int n = t->y - h + 1; + t->y -= n; + t->sr_y1 -= n; + t->sr_y2 -= n; + if (t->sr_y1 < 0) t->sr_y1 = 0; + if (t->sr_y2 < 0) t->sr_y2 = 0; + while (n--) scroll(t, 0, t->h-1, 0); + } + + memset(p, 0, UU_BUF_SIZE(w, h)); + + rows = (void *)p; + p += h*sizeof(struct uurow *); + + for (i=0; i<h; i++, p+=UU_ROW_SIZE(w)) { + rows[i] = (void *)p; + if (i < t->h) + memcpy(rows[i], t->rows[i], UU_ROW_SIZE(wmin)); + rows[i]->idx = i; + rows[i]->x1 = 0; + rows[i]->x2 = w-1; + } + + t->w = w; + t->h = h; + t->rows = rows; + + if (t->x >= t->w) t->x = t->w - 1; + if (t->sr_y1 >= t->h) t->sr_y1 = t->h - 1; + if (t->sr_y2 >= t->h) t->sr_y2 = t->h - 1; +} + +void uuterm_reset(struct uuterm *t) +{ + reset(t); +} @@ -0,0 +1,63 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +void uutty_resize(int fd, int w, int h) +{ +#ifdef TIOCSWINSZ + struct winsize ws = { }; + ws.ws_col = w; + ws.ws_row = h; + ioctl(fd, TIOCSWINSZ, &ws); +#endif +} + +/* #define posix_openpt(x) open("/dev/ptmx", x) */ + +int uutty_open(char **cmd, int w, int h) +{ + int ptm, pts; + struct stat st; + + if (!cmd || !cmd[0] || stat(cmd[0], &st) < 0 + || !S_ISCHR(st.st_mode) + || (ptm = open(cmd[0], O_RDWR|O_NOCTTY)) < 0 + || (isatty(ptm) ? 0 : (close(ptm),1)) ) { + + if ((ptm = posix_openpt(O_RDWR|O_NOCTTY)) < 0) + return -1; + if (grantpt(ptm) < 0 || unlockpt(ptm) < 0) { + close(ptm); + return -1; + } + + switch(fork()) { + case -1: + close(ptm); + return -1; + case 0: + setsid(); + pts = open(ptsname(ptm), O_RDWR); + close(ptm); + dup2(pts, 0); + dup2(pts, 1); + dup2(pts, 2); + if (pts > 2) close(pts); + // FIXME............................ + if (cmd) execvp(cmd[0], cmd); + else execl("/bin/sh", "-sh", (char *)0); + return 1; + } + + uutty_resize(ptm, w, h); + } + + fcntl(ptm, F_SETFL, fcntl(ptm, F_GETFL)|O_NONBLOCK); + + return ptm; +} diff --git a/uuterm.h b/uuterm.h new file mode 100644 index 0000000..f392bda --- /dev/null +++ b/uuterm.h @@ -0,0 +1,100 @@ +/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ + +#include <stddef.h> +#include <wchar.h> /* for mbstate_t... */ + +struct uucell +{ + unsigned short a; + unsigned char c[8]; +}; + +struct uurow +{ + int idx; + int x1, x2; /* dirty region */ + struct uucell cells[1]; +}; + +#define UU_ATTR_DIM 0x0100 +#define UU_ATTR_UL 0x0200 +#define UU_ATTR_REV 0x0400 + +#define UU_ATTR_BOLD 0x0008 +#define UU_ATTR_FG 0x0007 + +#define UU_ATTR_BLINK 0x0080 +#define UU_ATTR_BG 0x0070 + +struct uuterm +{ + struct uurow **rows; + int w, h; + + // all members past this point are zero-filled on reset! + int reset; + + // output state + int x, y; + int attr; + int sr_y1, sr_y2; + int ins :1; + int am :1; + int noam :1; + + // input state + int ckp :1; + int kp :1; + char reslen; + char res[16]; + + // saved state + int save_x, save_y; + int save_attr, save_fg, save_bg; + + // escape sequence processing + int esc; + unsigned param[16]; + int nparam; + + // multibyte parsing + mbstate_t mbs; +}; + +struct uudisp +{ + int cell_w, cell_h; + int w, h; + int inlen; + unsigned char *intext; + unsigned char inbuf[16]; + int blink; + long priv[64]; +}; + +#define UU_FULLWIDTH 0xfffe + +#define UU_ROW_SIZE(w) (sizeof(struct uurow) + (w)*sizeof(struct uucell)) +#define UU_BUF_SIZE(w, h) ( (h) * (sizeof(struct uurow *) * UU_ROW_SIZE((w))) ) + +void uuterm_reset(struct uuterm *); +void uuterm_replace_buffer(struct uuterm *, int, int, void *); +void uuterm_stuff_byte(struct uuterm *, unsigned char); + +void uuterm_refresh_row(struct uudisp *, struct uurow *, int, int); + +int uu_combine_involution(unsigned, unsigned); + +int uudisp_open(struct uudisp *); +int uudisp_fd_set(struct uudisp *, int, void *); +void uudisp_next_event(struct uudisp *, void *); +void uudisp_close(struct uudisp *); +void uudisp_refresh(struct uudisp *, struct uuterm *); +void uudisp_draw_glyph(struct uudisp *, int, int, const void *, int); + +void *uuterm_alloc(size_t); +void uuterm_free(void *); +void *uuterm_buf_alloc(int, int); + +void uutty_resize(int, int, int); +int uutty_open(char **, int, int); |