├── VERSION ├── unix.h ├── kmaps ├── ligatures ├── fonts ├── fixed10.fbf ├── fixed12.fbf ├── fixed13.fbf ├── fixed14.fbf ├── helv10.fbf ├── helv12.fbf ├── helv14.fbf ├── helv18.fbf ├── helv24.fbf ├── helv8.fbf ├── times10.fbf ├── times12.fbf ├── times14.fbf ├── times18.fbf ├── times24.fbf ├── times8.fbf └── unifont.fbf ├── fbftoqe.dSYM └── Contents │ ├── Resources │ └── DWARF │ │ └── fbftoqe │ └── Info.plist ├── libqhtml ├── csstoqe.dSYM │ └── Contents │ │ ├── Resources │ │ └── DWARF │ │ │ └── csstoqe │ │ └── Info.plist ├── Makefile ├── cssid.h ├── csstoqe.c └── html.css ├── .travis.yml ├── qeend.c ├── tests ├── test-hebrew ├── test-capital-rtl ├── test-capital-rtl.ref ├── TestPage.txt ├── HELLO.txt └── testbidi.html ├── cfb.h ├── .gitignore ├── plugin-example ├── my_plugin.c └── Makefile ├── README ├── fbfrender.h ├── qe.tcc ├── config.eg ├── README.md ├── docbook.c ├── qe.1 ├── fbftoqe.c ├── qemacs.spec ├── TODO ├── qestyles.h ├── qfribidi.h ├── cutils.h ├── xterm-146-dw-patch ├── list.c ├── libfbf.h ├── indic.c ├── Changelog ├── unihex.c ├── cutils.c ├── mpeg.c ├── bufed.c ├── cptoqe.c ├── display.h ├── xml.c ├── display.c ├── ligtoqe.c ├── input.c ├── qeconfig.h ├── kmaptoqe.c ├── unix.c ├── Makefile ├── charsetmore.c ├── charset.c ├── unicode_join.c ├── arabic.c └── hex.c /VERSION: -------------------------------------------------------------------------------- 1 | 0.3.3 2 | -------------------------------------------------------------------------------- /unix.h: -------------------------------------------------------------------------------- 1 | /* block until one event */ 2 | 3 | -------------------------------------------------------------------------------- /kmaps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/kmaps -------------------------------------------------------------------------------- /ligatures: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/ligatures -------------------------------------------------------------------------------- /fonts/fixed10.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/fixed10.fbf -------------------------------------------------------------------------------- /fonts/fixed12.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/fixed12.fbf -------------------------------------------------------------------------------- /fonts/fixed13.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/fixed13.fbf -------------------------------------------------------------------------------- /fonts/fixed14.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/fixed14.fbf -------------------------------------------------------------------------------- /fonts/helv10.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv10.fbf -------------------------------------------------------------------------------- /fonts/helv12.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv12.fbf -------------------------------------------------------------------------------- /fonts/helv14.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv14.fbf -------------------------------------------------------------------------------- /fonts/helv18.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv18.fbf -------------------------------------------------------------------------------- /fonts/helv24.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv24.fbf -------------------------------------------------------------------------------- /fonts/helv8.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/helv8.fbf -------------------------------------------------------------------------------- /fonts/times10.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times10.fbf -------------------------------------------------------------------------------- /fonts/times12.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times12.fbf -------------------------------------------------------------------------------- /fonts/times14.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times14.fbf -------------------------------------------------------------------------------- /fonts/times18.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times18.fbf -------------------------------------------------------------------------------- /fonts/times24.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times24.fbf -------------------------------------------------------------------------------- /fonts/times8.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/times8.fbf -------------------------------------------------------------------------------- /fonts/unifont.fbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fonts/unifont.fbf -------------------------------------------------------------------------------- /fbftoqe.dSYM/Contents/Resources/DWARF/fbftoqe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/fbftoqe.dSYM/Contents/Resources/DWARF/fbftoqe -------------------------------------------------------------------------------- /libqhtml/csstoqe.dSYM/Contents/Resources/DWARF/csstoqe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdwije/qemacs/HEAD/libqhtml/csstoqe.dSYM/Contents/Resources/DWARF/csstoqe -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | before_install: 3 | - sudo chmod +x build/install-dependencies.sh 4 | - sudo ./build/install-dependencies.sh 5 | script: ./configure && make 6 | os: 7 | - linux 8 | - osx 9 | 10 | -------------------------------------------------------------------------------- /qeend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "qe.h" 3 | 4 | /* add empty pointers at the end of init and cleanup sections */ 5 | static int (*__initcall_end)(void) __init_call = NULL; 6 | 7 | static void (*__exitcall_end)(void) __exit_call = NULL; 8 | -------------------------------------------------------------------------------- /tests/test-hebrew: -------------------------------------------------------------------------------- 1 | שלום abc 2 | abc שלום 3 | abc שלום cde 4 | he said: "זה לא נכון!" 5 | he said: "זה לא נכון!‏" 6 | (שלום) abc 7 | abc (שלום) 8 | #@$ שלום 9 |

שלום

10 | שלום 23 שלום abc 11 | שלום ~~~23%%% שלום abc 12 | שלום abc ~~~23%%% שלום abc 13 | שלום abc@23@cde שלום 14 | שלום abc 23 cde שלום 15 | שלום abc 23 שלום abc 16 | <שלום>Shalom 17 | שa 2 ש 18 | -------------------------------------------------------------------------------- /tests/test-capital-rtl: -------------------------------------------------------------------------------- 1 | car is THE CAR in arabic 2 | CAR IS the car IN ENGLISH 3 | he said "IT IS 123, 456, OK" 4 | he said "IT IS (123, 456), OK" 5 | he said "IT IS 123,456, OK" 6 | he said "IT IS (123,456), OK" 7 | HE SAID "it is 123, 456, ok" 8 | shalom 9 | SAALAM 10 | HE SAID "it is a car!" AND RAN 11 | HE SAID "it is a car!x" AND RAN 12 | -2 CELSIUS IS COLD 13 | SOLVE 1*5 1-5 1/5 1+5 14 | THE RANGE IS 2.5..5 15 | IOU $10 16 | CHANGE -10% 17 | -10% CHANGE 18 | -------------------------------------------------------------------------------- /cfb.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct CFBContext { 3 | unsigned char *base; 4 | int bpp; /* number of bytes per pixel */ 5 | int depth; /* number of color bits per pixel */ 6 | int wrap; 7 | unsigned int (*get_color)(unsigned int); 8 | void (*draw_glyph)(QEditScreen *s1, 9 | int x1, int y1, int w, int h, QEColor color, 10 | unsigned char *glyph, int glyph_wrap); 11 | } CFBContext; 12 | 13 | int cfb_init(QEditScreen *s, 14 | void *base, int wrap, int depth, const char *font_path); 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Executables 2 | qe 3 | qe_g 4 | qe.exe 5 | 6 | # Object files 7 | *.o 8 | *.ko 9 | *.obj 10 | *.elf 11 | 12 | # Precompiled Headers 13 | *.gch 14 | *.pch 15 | 16 | # Libraries 17 | *.lib 18 | *.a 19 | *.la 20 | *.lo 21 | 22 | # Shared objects (inc. Windows DLLs) 23 | *.dll 24 | *.so 25 | *.so.* 26 | *.dylib 27 | 28 | # Executables 29 | *.exe 30 | *.out 31 | *.app 32 | *.i*86 33 | *.x86_64 34 | *.hex 35 | 36 | # tmp files 37 | *~ 38 | *# 39 | 40 | 41 | config.mak 42 | config.h 43 | csstoqe 44 | html_style.c 45 | docbook_style.c 46 | *.o 47 | gmon.out 48 | qfribidi 49 | kmaptoqe 50 | ligtoqe 51 | html2png 52 | fbftoqe 53 | fbffonts.c -------------------------------------------------------------------------------- /plugin-example/my_plugin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple plugin example 3 | */ 4 | #include "qe.h" 5 | 6 | /* insert 'hello' at the current cursor position */ 7 | static void insert_hello(EditState *s) 8 | { 9 | static char hello[] = "Hello"; 10 | int len; 11 | len = strlen(hello); 12 | 13 | eb_insert(s->b, s->offset, hello, len); 14 | s->offset += len; 15 | } 16 | 17 | static CmdDef my_commands[] = { 18 | CMD0( KEY_CTRLX('h'), KEY_NONE, "insert-hello", insert_hello) 19 | CMD_DEF_END, 20 | }; 21 | 22 | static int my_plugin_init(void) 23 | { 24 | /* commands and default keys */ 25 | qe_register_cmd_table(my_commands, NULL); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | qe_module_init(my_plugin_init); 32 | -------------------------------------------------------------------------------- /fbftoqe.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.apple.xcode.dsym.fbftoqe 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | dSYM 13 | CFBundleSignature 14 | ???? 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /libqhtml/csstoqe.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.apple.xcode.dsym.csstoqe 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | dSYM 13 | CFBundleSignature 14 | ???? 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /libqhtml/Makefile: -------------------------------------------------------------------------------- 1 | include ../config.mak 2 | 3 | CFLAGS:=-Wall -g $(CFLAGS) 4 | ifdef TARGET_GPROF 5 | CFLAGS+= -p 6 | LDFLAGS+= -p 7 | endif 8 | ifdef TARGET_ARCH_X86 9 | #CFLAGS+=-fomit-frame-pointer 10 | ifeq ($(GCC_MAJOR),2) 11 | CFLAGS+=-m386 -malign-functions=0 12 | else 13 | CFLAGS+=-march=i386 -falign-functions=0 14 | endif 15 | endif 16 | CFLAGS+=-I.. 17 | 18 | OBJS=css.o xmlparse.o cssparse.o html_style.o docbook_style.o 19 | LIB=libqhtml.a 20 | 21 | all: $(LIB) 22 | 23 | $(LIB): $(OBJS) 24 | rm -f $@ 25 | $(AR) rc $@ $(OBJS) 26 | 27 | clean: 28 | rm -f *~ *.o *.a csstoqe html_style.c docbook_style.c 29 | 30 | # 31 | # build default style sheet file 32 | # 33 | csstoqe: csstoqe.c 34 | $(HOST_CC) $(CFLAGS) -o $@ $< 35 | 36 | html_style.c: html.css csstoqe 37 | ./csstoqe html_style < $< > $@ 38 | 39 | docbook_style.c: docbook.css csstoqe 40 | ./csstoqe docbook_style < $< > $@ 41 | -------------------------------------------------------------------------------- /plugin-example/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # QEmacs sample Makefile to develop plugins 3 | # 4 | # QEmacs plugins can contain modes, bindings, or any other qemacs 5 | # dynamically registerable resource. 6 | # 7 | 8 | # modify to get the path of the qemacs sources 9 | QEMACS_PATH=../ 10 | # define the name of your plugin 11 | LIB=my_plugin.so 12 | # define the object files it contains 13 | OBJS=my_plugin.o 14 | 15 | INCLUDES=-I$(QEMACS_PATH) 16 | DEFINES=-DQE_MODULE 17 | DIST_LIB:=$(HOME)/.qe/$(LIB) 18 | CC=gcc 19 | CFLAGS=-O2 -Wall -g -fPIC $(INCLUDES) $(DEFINES) 20 | 21 | # by default, the plugin is copied in ~/.qe/ some that qemacs can load 22 | # it automatically. 23 | all: $(DIST_LIB) 24 | 25 | $(DIST_LIB): $(LIB) 26 | install -s -m 644 $< $@ 27 | 28 | install: $(DIST_LIB) 29 | 30 | $(LIB): $(OBJS) Makefile 31 | $(CC) -shared -o $@ $(OBJS) 32 | 33 | %.o: %.c 34 | $(CC) $(CFLAGS) -c -o $@ $< 35 | 36 | clean: 37 | rm -f *.o *.so *~ 38 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------- 2 | Compiling 3 | ---------------------------------------------------------- 4 | 5 | * If you want image, audio and video support, download FFmpeg at 6 | http://ffmpeg.org and install it in the qemacs/ directory (it should 7 | be in qemacs/ffmpeg). 8 | 9 | * Launch the configure tool './configure'. You can look at the 10 | possible options by typing './configure --help'. 11 | 12 | * Type 'make' to compile qemacs and its associated tools. 13 | 14 | * type 'make install' as root to install it in /usr/local. 15 | 16 | ---------------------------------------------------------- 17 | Documentation 18 | ---------------------------------------------------------- 19 | 20 | Read the file qe-doc.html. 21 | 22 | ---------------------------------------------------------- 23 | Licensing 24 | ---------------------------------------------------------- 25 | 26 | QEmacs is released under the GNU Lesser General Public License (read 27 | the accompagning COPYING file). 28 | 29 | Fabrice Bellard. 30 | -------------------------------------------------------------------------------- /fbfrender.h: -------------------------------------------------------------------------------- 1 | 2 | /* glyph cache */ 3 | typedef struct GlyphCache { 4 | struct GlyphCache *hash_next; 5 | struct GlyphCache *prev, *next; 6 | void *private; /* private data available for the driver, initialized to NULL */ 7 | /* font info */ 8 | short size; /* font size */ 9 | unsigned short style; /* font style */ 10 | short w, h; /* glyph bitmap size */ 11 | short x, y; /* glyph bitmap offset */ 12 | unsigned short index; /* glyph index */ 13 | unsigned short data_size; 14 | short xincr; /* glyph x increment */ 15 | unsigned char is_fallback; /* true if fallback glyph */ 16 | unsigned char data[0]; 17 | } GlyphCache; 18 | 19 | void fbf_text_metrics(QEditScreen *s, QEFont *font, 20 | QECharMetrics *metrics, 21 | const unsigned int *str, int len); 22 | GlyphCache *decode_cached_glyph(QEditScreen *s, QEFont *font, int code); 23 | QEFont *fbf_open_font(QEditScreen *s, int style, int size); 24 | void fbf_close_font(QEditScreen *s, QEFont *font); 25 | 26 | int fbf_render_init(const char *font_path); 27 | void fbf_render_cleanup(void); 28 | -------------------------------------------------------------------------------- /qe.tcc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # QEmacs can be compiled directly with TinyCC. Launch this script to 4 | # compile and execute qemacs with TinyCC. 5 | # 6 | 7 | # just for benchmarking 8 | tcc_opts="" 9 | libs="-L/usr/X11R6/lib -lXext -lXv -lX11" 10 | #tcc="tcc" 11 | tcc="../tcc/tcc" 12 | if [ "$1" = "-bench" ] ; then 13 | tcc_opts="$tcc_opts -o /tmp/qe -bench" 14 | shift 15 | fi 16 | if [ "$1" = "-gprof" ] ; then 17 | tcc="${tcc}_p" 18 | libs="" 19 | shift 20 | fi 21 | if [ "$1" = "-g" ] ; then 22 | tcc_opts="$tcc_opts -g" 23 | shift 24 | fi 25 | if [ "$1" = "-b" ] ; then 26 | tcc_opts="$tcc_opts -b" 27 | shift 28 | fi 29 | 30 | $tcc $tcc_opts $libs -DHAVE_QE_CONFIG_H -DQE_VERSION=\"0.3tcc\" -Iliburlio -- \ 31 | qe.c charset.c buffer.c input.c unicode_join.c \ 32 | qfribidi.c \ 33 | display.c tty.c util.c hex.c list.c \ 34 | clang.c shell.c \ 35 | css.c cssparse.c xmlparse.c html.c html_style.c \ 36 | x11.c \ 37 | liburlio/cutils.c liburlio/urlmisc.c liburlio/mem.c \ 38 | liburlio/urlio.c liburlio/file.c liburlio/dns.c \ 39 | liburlio/tcp.c liburlio/http.c \ 40 | qeend.c -- $* 41 | -------------------------------------------------------------------------------- /config.eg: -------------------------------------------------------------------------------- 1 | // Sample qemacs config file 2 | // 3 | // copy it in ~/.qe/config 4 | // 5 | // You can call any Qemacs command with a C like syntax. 6 | // 7 | // underscores can be used in command names instead of dash. 8 | // 9 | 10 | // simple key definition 11 | // C-key : Control + key 12 | // M-key : Meta + key 13 | // Read util.c to get all the key names 14 | global_set_key("C-x s", "set-style"); 15 | 16 | // set X11 display size 17 | set_display_size(80, 50); 18 | 19 | // set default input method 20 | //set_input_method("HebrewIsraeli"); 21 | 22 | // set X11 fonts and fall backs 23 | set_system_font("fixed", "fixed,unifont"); 24 | set_system_font("sans", "helvetica,unifont"); 25 | set_system_font("serif", "times,unifont"); 26 | 27 | // simple styles 28 | set_style("mode-line", "background-color", "white"); 29 | set_style("comment", "font-family", "sans"); 30 | set_style("comment", "font-size", "12"); 31 | set_style("comment", "font-style", "italic"); 32 | 33 | set_style("keyword", "font-family", "serif"); 34 | set_style("keyword", "font-size", "18"); 35 | 36 | set_style("function", "font-family", "serif"); 37 | set_style("function", "font-size", "18"); 38 | set_style("function", "font-weight", "bold"); 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QEmacs 2 | === 3 | 4 | This is a development fork of [QEmacs](http://www.bellard.org/qemacs/). 5 | 6 | [![Build Status](https://travis-ci.org/jdwije/qemacs.svg?branch=osx-driver)](https://travis-ci.org/jdwije/qemacs) 7 | 8 | 1. [ ] Bug fixing and stabilizing the software (WIP) 9 | 2. [ ] Getting cross platform compilation working again and port to OSX 10 | - [x] OSX 11 | - [x] Linux 12 | - [ ] Windows 13 | 3. [ ] A native osx driver (WIP) 14 | 15 | ## Compiling 16 | 17 | 1. If you want image, audio and video support, download FFmpeg at 18 | http://ffmpeg.org. Compile, then install it in the qemacs/ directory (it should 19 | be in qemacs/ffmpeg). 20 | 2. Launch the configure tool './configure'. You can look at the 21 | possible options by typing './configure --help'. 22 | 3. Type 'make' to compile qemacs and its associated tools. 23 | 4. Type 'make install' as root to install it in /usr/local 24 | 25 | ## Documentation 26 | 27 | See [qe-doc.md](http://github.com/jdwije/qemacs/blob/master/qe-doc.md) or alternatively read qe-doc.html or qe-doc.texi for the official docs. 28 | 29 | ## Licensing 30 | 31 | QEmacs is released under the GNU Lesser General Public License, please read the accompanying LICENSE.md file. 32 | 33 | Copyright holder [Fabrice Bellard](http://www.bellard.org). 34 | -------------------------------------------------------------------------------- /tests/test-capital-rtl.ref: -------------------------------------------------------------------------------- 1 | car is THE CAR in arabic => car is RAC EHT in arabic 2 | CAR IS the car IN ENGLISH => HSILGNE NI the car SI RAC 3 | he said "IT IS 123, 456, OK" => he said "KO ,456 ,123 SI TI" 4 | he said "IT IS (123, 456), OK" => he said "KO ,(456 ,123) SI TI" 5 | he said "IT IS 123,456, OK" => he said "KO ,123,456 SI TI" 6 | he said "IT IS (123,456), OK" => he said "KO ,(123,456) SI TI" 7 | HE SAID "it is 123, 456, ok" => "it is 123, 456, ok" DIAS EH 8 | shalom => <123H/>shalom<123H> 9 | SAALAM => MALAAS 10 | HE SAID "it is a car!" AND RAN => NAR DNA "!it is a car" DIAS EH 11 | HE SAID "it is a car!x" AND RAN => NAR DNA "it is a car!x" DIAS EH 12 | -2 CELSIUS IS COLD => DLOC SI SUISLEC -2 13 | SOLVE 1*5 1-5 1/5 1+5 => 1+5 1/5 1-5 5*1 EVLOS 14 | THE RANGE IS 2.5..5 => 5..2.5 SI EGNAR EHT 15 | IOU $10 => $10 UOI 16 | CHANGE -10% => -10% EGNAHC 17 | -10% CHANGE => EGNAHC -10% 18 | -------------------------------------------------------------------------------- /tests/TestPage.txt: -------------------------------------------------------------------------------- 1 | ************ Hungarian - Magyar **************** 2 | A tanyákon túl a puszta mélyén 3 | Áll magányos, dőlt kéményű csárda; 4 | Látogatják a szomjas betyárok, 5 | Kecskemétre menvén a vásárra. 6 | ************ Russian - Русский ************ 7 | Следователь. Вы догадываетесь, почему вас вызвали? 8 | Свидетель. Да, но лучше будет, если вы скажете. 9 | Следователь. Почему лучше? 10 | Свидетель. В противном случае получается, что вам стыдно сказать. 11 | (Из рассказов о допросе.) 12 | ************ Greek - ΕΛΛΗΝΙΚΑ **************** 13 | Στο στήθος μου η πληγή ανοίγει πάλι 14 | όταν χαμηλώνουν τ' άστρα και συγγενεύουν με το κορμί μου 15 | όταν πέφτει σιγή κάτω από τα πέλματα των ανθρώπων. 16 | Αυτές οι πέτρες που βουλιάζουν μέσα στα χρόνια ως πού θα με παρασύρουν; 17 | Τη θάλασσα τη θάλασσα, ποιός θα μπορέσει να την εξαντλήσει; 18 | **************** Japanese 日本語 **************** 19 | 人妻ゆゑに 我恋ひめやも 紫のにほへる妹を憎くあらば 20 | 大海人皇子 巻一|二十一 21 | 野守は見ずや 君が袖振る あかねさす 紫野行き 標野行き 22 | 額田王 巻一|二十 23 | **************** Chinese 中文 **************** 24 | 古原草     白居易 25 | 离离原上草,一岁一枯荣。 26 | 野火烧不尽,春风吹又生。 27 | 远芳侵古道,晴翠接荒城。 28 | 又送王孙去,萋萋满别情。 29 | ***************** Korean 한국어 ************************ 30 | 별 : 김남주 31 | 밤 들어 세상은/온통 고요한데/그리워 못 잊어 홀로 잠 못 이뤄 32 | 불 밝혀 지새우는 것이 있다./사람들은 그것을 별이라 그런다. 33 | 기약이라 소망이라 그런다./밤 깊어/가장 괴로울 때면 34 | 사람들은 저마다 별이 되어/어머니 어머니라 부른다. 35 | ************ French - Français **************** 36 | Juste un petit exemple pour dire que les français aussi 37 | ont à cœur de pouvoir utiliser tous leurs caractères ! :) 38 | -------------------------------------------------------------------------------- /libqhtml/cssid.h: -------------------------------------------------------------------------------- 1 | /* definition of builtin CSS identifiers for easy testing in C code */ 2 | 3 | CSSID(class) 4 | CSSID(id) 5 | CSSID(img) 6 | CSSID(width) 7 | CSSID(height) 8 | CSSID(body) 9 | CSSID(text) 10 | CSSID(font) 11 | CSSID(basefont) 12 | CSSID(size) 13 | CSSID(color) 14 | CSSID(bgcolor) 15 | CSSID(align) 16 | CSSID(style) 17 | CSSID(script) 18 | CSSID(li) 19 | CSSID(b) 20 | CSSID(i) 21 | CSSID(em) 22 | CSSID(br) 23 | CSSID(hr) 24 | CSSID(meta) 25 | CSSID(link) 26 | CSSID(form) 27 | CSSID(base) 28 | CSSID(input) 29 | CSSID(td) 30 | CSSID(th) 31 | CSSID(tr) 32 | CSSID(dt) 33 | CSSID(dd) 34 | CSSID(table) 35 | CSSID(a) 36 | CSSID(href) 37 | CSSID(border) 38 | CSSID(clear) 39 | CSSID(cellspacing) 40 | CSSID(cellpadding) 41 | CSSID(valign) 42 | CSSID(type) 43 | CSSID(value) 44 | CSSID(button) 45 | CSSID(reset) 46 | CSSID(submit) 47 | CSSID(password) 48 | CSSID(textarea) 49 | CSSID(cols) 50 | CSSID(rows) 51 | CSSID(select) 52 | CSSID(image) 53 | CSSID(file) 54 | CSSID(caption) 55 | CSSID(ol) 56 | CSSID(colspan) 57 | CSSID(rowspan) 58 | CSSID(col) 59 | CSSID(colgroup) 60 | CSSID(hspace) 61 | CSSID(vspace) 62 | CSSID(alt) 63 | CSSID(src) 64 | CSSID(programlisting) 65 | CSSIDSTR(list_item, "list-item") 66 | CSSID(start) 67 | CSSID(html) 68 | -------------------------------------------------------------------------------- /tests/HELLO.txt: -------------------------------------------------------------------------------- 1 | This is a list of ways to say hello in various languages. 2 | Its purpose is to illustrate a number of scripts. 3 | 4 | --------------------------------------------------------- 5 | Amharic (አማርኛ) ሠላም 6 | Arabic ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ 7 | Czech (česky) Dobrý den 8 | Danish (Dansk) Hej, Goddag 9 | English Hello 10 | Esperanto Saluton 11 | Estonian Tere, Tervist 12 | FORTRAN PROGRAM 13 | Finnish (Suomi) Hei 14 | French (Français) Bonjour, Salut 15 | German (Deutsch Nord) Guten Tag 16 | German (Deutsch Süd) Grüß Gott 17 | Greek (Ελληνικά) Γειά σας 18 | Hebrew שלום 19 | Hindi \mf00086\mf0008c\mf000f7\mf00082\mf000a1, \mf00086\mf0008c\mf000f7\mfb0073\mf0009a\mf0008f \mf000aa 20 | Italiano Ciao, Buon giorno 21 | Lao(ພາສາລາວ) ສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ 22 | Maltese Ciao 23 | Nederlands, Vlaams Hallo, Dag 24 | Norwegian (Norsk) Hei, God dag 25 | Polish Dzień dobry, Hej 26 | Russian (Русский) Здравствуйте! 27 | Slovak Dobrý deň 28 | Spanish (Español) ¡Hola! 29 | Swedish (Svenska) Hej, Goddag 30 | Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ 31 | 32 | Tibetan (\mfc00d7\mfc00fd\mfc00d2\mf1007b\mfc0210\mfc00f1\mfc00d2\mf1007b) \mfc00d7\mfc01b0\mfc00f1\mf1007b\mfc00e5\mfc00f3\mfc00e7\mf1007b\mfc00d7\mfc00d2\mfc00fb\mf1007b\mfc00e4\mfc00fb\mfc00c3\mfc00e7\mfc007e 33 | Tigrigna (ትግርኛ) ሰላማት 34 | Turkish (Türkçe) Merhaba 35 | Vietnamese (Tiếng Việt) Chào bạn 36 | 37 | Japanese (日本語) こんにちは, コンニチハ 38 | Chinese (中文,普通话,汉语) 你好 39 | Cantonese (粵語,廣東話) 早晨, 你好 40 | Korean (한글) 안녕하세요, 안녕하십니까 41 | 42 | Difference among chinese characters in GB, JIS, KSC, BIG5: 43 | GB -- 元气 开发 44 | JIS -- 元気 開発 45 | KSC -- 元氣 開發 46 | BIG5 -- 元氣 開發 47 | 48 | Just for a test of JISX0212: 騏驎 (the second character is of JISX0212) 49 | -------------------------------------------------------------------------------- /tests/testbidi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 |

bidi test

16 | 17 |

standard test

18 | 19 |

car is THE CAR in arabic

20 |

CAR IS the car IN ENGLISH

21 |

he said "IT IS 123, 456, OK"

22 |

he said "IT IS (123, 456), OK"

23 |

he said "IT IS 123,456, OK"

24 |

he said "IT IS (123,456), OK"

25 |

HE SAID "it is 123, 456, ok"

26 |

<H123>shalom</H123>

27 |

<h123>SAALAM</h123>

28 |

HE SAID "it is a car!" AND RAN

29 |

HE SAID "it is a car!x" AND RAN

30 |

-2 CELSIUS IS COLD

31 |

SOLVE 1*5 1-5 1/5 1+5

32 |

THE RANGE IS 2.5..5

33 |

IOU $10

34 |

CHANGE -10%

35 |

-10% CHANGE

36 | 37 |

image test

38 | 39 |

car is TimgHE CAR in arabic

40 | 41 |

override test

42 | 43 |

car is TimgHE CAR in 44 | arabic tralala

46 | 47 |

css2 spec example

48 | 49 | 50 | HEBREW1 HEBREW2 english3 HEBREW4 HEBREW5 51 | HEBREW6 HEBREW7 HEBREW8 52 | 53 | 54 | english9 english10 english11 HEBREW12 HEBREW13 55 | english14 english15 english16 56 | english17 HEBREW18 english19 HEBREW20 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /docbook.c: -------------------------------------------------------------------------------- 1 | /* 2 | * WYSIWYG Docbook ode for QEmacs. 3 | * Copyright (c) 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | #include "css.h" 21 | 22 | extern const char docbook_style[]; 23 | 24 | static int docbook_mode_probe(ModeProbeData *p1) 25 | { 26 | if (xml_mode_probe(p1) == 0) 27 | return 0; 28 | /* well, very crude, but it may work OK */ 29 | if (strstr((char *)p1->buf, "DocBook")) 30 | return 100; 31 | return 0; 32 | } 33 | 34 | static int docbook_mode_init(EditState *s, ModeSavedData *saved_data) 35 | { 36 | return gxml_mode_init(s, saved_data, XML_IGNORE_CASE | XML_DOCBOOK, docbook_style); 37 | } 38 | 39 | ModeDef docbook_mode; 40 | 41 | static int docbook_init(void) 42 | { 43 | /* inherit from html mode */ 44 | memcpy(&docbook_mode, &html_mode, sizeof(ModeDef)); 45 | docbook_mode.name = "docbook"; 46 | docbook_mode.mode_probe = docbook_mode_probe; 47 | docbook_mode.mode_init = docbook_mode_init; 48 | 49 | qe_register_mode(&docbook_mode); 50 | return 0; 51 | } 52 | 53 | qe_module_init(docbook_init); 54 | -------------------------------------------------------------------------------- /qe.1: -------------------------------------------------------------------------------- 1 | .\" Hey, EMACS: -*- nroff -*- 2 | .TH QE 1 "October 21, 2001" 3 | .\" Please adjust this date whenever revising the manpage. 4 | .SH NAME 5 | QEmacs \- tiny full-screen editor 6 | .SH SYNOPSIS 7 | .B qe 8 | .RB [options] 9 | .RI file... 10 | .SH DESCRIPTION 11 | .B qemacs 12 | is a tiny editor targetted at embedded systems or 13 | debugging. Although it is very small, it has some very interesting 14 | features that even big editors lack : 15 | 16 | - Full screen editor with an Emacs look and feel with all Emacs common 17 | features: multi-buffer, multi-window, command mode, universal 18 | argument, keyboard macros, config file with C like syntax, minibuffer 19 | with completion and history. 20 | 21 | - Can edit files of hundreds of Megabytes without being slow by using 22 | a highly optimized internal representation and by mmaping the file. 23 | 24 | - Full UTF8 support, including bidirectional editing respecting the 25 | Unicode bidi algorithm. Arabic and Indic scripts handling (in 26 | progress). 27 | 28 | - C mode: coloring with immediate update. Emacs like auto-indent. 29 | 30 | - Shell mode: colorized VT100 emulation so that your shell work 31 | exactly as you expect. Compile mode with next/prev error. 32 | 33 | - Input methods for most languages, including Chinese (input methods 34 | come from the Yudit editor). 35 | 36 | - Hexadecimal editing mode with insertion and block commands. Unicode 37 | hexa editing of UTF8 files also supported. 38 | 39 | - Works on any VT100 terminals without termcap. UTF8 VT100 support 40 | included with double width glyphs. 41 | 42 | - X11 support. Support multiple proportionnal fonts at the same time 43 | (as XEmacs). X Input methods supported. Xft extension supported for 44 | anti aliased font display. 45 | .PP 46 | For more information and a list of key bindings please see 47 | /usr/share/doc/qemacs/README.gz. 48 | .SH AUTHOR 49 | This manual page was written by Edmund GRIMLEY EVANS , 50 | for the Debian GNU/Linux system (but may be used by others). 51 | -------------------------------------------------------------------------------- /fbftoqe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * convert FBF fonts into source file so that so resources are needed 3 | * for fonts 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | void dump_font(const char *filename, const char *name) 11 | { 12 | int c; 13 | FILE *f; 14 | int j; 15 | 16 | f = fopen(filename, "r"); 17 | if (!f) { 18 | perror(filename); 19 | exit(1); 20 | } 21 | printf("static const unsigned char font_%s[] = {\n", name); 22 | j = 0; 23 | for(;;) { 24 | c = fgetc(f); 25 | if (c == EOF) 26 | break; 27 | j++; 28 | printf("0x%02x,", c); 29 | if ((j & 7) == 0) 30 | printf("\n"); 31 | else 32 | printf(" "); 33 | } 34 | if ((j & 7) != 0) 35 | printf("\n"); 36 | printf("};\n\n"); 37 | 38 | fclose(f); 39 | } 40 | 41 | void getname(char *name, int name_size, const char *filename) 42 | { 43 | const char *p; 44 | char *q; 45 | 46 | p = strrchr(filename, '/'); 47 | if (!p) 48 | p = filename; 49 | else 50 | p++; 51 | strcpy(name, p); 52 | q = strrchr(name, '.'); 53 | if (q) 54 | *q = '\0'; 55 | } 56 | 57 | int main(int argc, char **argv) 58 | { 59 | const char *filename; 60 | char name[128]; 61 | int i; 62 | 63 | printf("#include \"qe.h\"\n\n"); 64 | 65 | for(i=1;i 0.2-1 63 | - initial spec file. Added patch that also includes all of yudit's maps 64 | 65 | # end of file 66 | -------------------------------------------------------------------------------- /libqhtml/csstoqe.c: -------------------------------------------------------------------------------- 1 | /* convert a CSS style sheet to C buffer so that it can be statically 2 | linked with qemacs */ 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int c, n, last_c, got_space, in_string; 10 | 11 | printf("/* Automatically generated file - do not edit */\n"); 12 | printf("const char %s[] =\n", argv[1]); 13 | n = 0; 14 | got_space = 0; 15 | last_c = 0; 16 | in_string = 0; 17 | for(;;) { 18 | c = getchar(); 19 | redo: 20 | if (c == EOF) 21 | break; 22 | if (!in_string) { 23 | if (c == ' ' || c == '\t' || c == '\n') { 24 | got_space = 1; 25 | continue; 26 | } 27 | /* comments */ 28 | if (c == '/') { 29 | c = getchar(); 30 | if (c != '*') { 31 | putchar('/'); 32 | goto redo; 33 | } 34 | for(;;) { 35 | c = getchar(); 36 | if (c == EOF) 37 | goto the_end; 38 | while (c == '*') { 39 | c = getchar(); 40 | if (c == EOF) 41 | goto the_end; 42 | if (c == '/') 43 | goto end_comment; 44 | } 45 | } 46 | end_comment: 47 | got_space = 1; 48 | continue; 49 | } 50 | } 51 | if (n == 0) 52 | printf("\""); 53 | /* add separator if needed */ 54 | if (!in_string && got_space && isalnum(c) && isalnum(last_c)) 55 | putchar(' '); 56 | if (c == '\"' || c == '\'' || c == '\\') 57 | putchar('\\'); 58 | putchar(c); 59 | if (c == '\"') 60 | in_string ^= 1; 61 | last_c = c; 62 | got_space = 0; 63 | if (++n >= 64) { 64 | printf("\"\n"); 65 | n = 0; 66 | } 67 | } 68 | the_end: 69 | if (n > 0) 70 | printf("\"\n"); 71 | printf(";\n\n"); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | General TODO: 2 | ------------ 3 | - regex search/replace (use glibc 2.1 regex.c file) 4 | - tab cursor displayed size 5 | - fix kana input method 6 | - current path in compile set to current buffer path 7 | - avoid problems with popups (kill_buffer, delete_window, split_window) 8 | - avoid error in new file 9 | - faster video handling (generalize invalidate region system) 10 | - check file permissions. 11 | - faster search 12 | - bufed segfault 13 | - distribute libqhtml as a separate project 14 | - integrate tinySVG renderer based on the new libraster. 15 | - improve speed of text renderer / improve truncate mode (merge some 16 | good parts with CSS renderer ?). Suppress CRC hack (not reliable). 17 | - set_input_method() and set_buffer_file_coding_system() in config 18 | file. 19 | - add custom memory handling functions. 20 | - charset: add JIS missing encoding functions 21 | - display alternate cursor in non activate column in hex mode. 22 | - implement wheel mode in CSS display. 23 | - check console charset support (need to convert input?) 24 | - test Hebrew keymap support. 25 | 26 | C mode TODO: 27 | ----------- 28 | - add TAGS support: 29 | * recursive search of QTAGS file. 30 | * C decl parser 31 | * man like mode 32 | * global QTAGS file indexed with global includes 33 | - see if java/javascript/c++ is OK. 34 | 35 | HTML mode TODO: 36 | -------------- 37 | 38 | - OPTIMIZE eb_nextc et al or always duplicate box content (big speed 39 | improvement). 40 | 41 | - polish end of line offset/cursor displacement support. 42 | 43 | - handle implicit TR 44 | 45 | - add file referencing (, 46 | , etc...) 47 | 48 | - fix LI numbering with VALUE attribute (cannot use CSS). Verify 49 | counter-reset semantics. 50 | 51 | - (z-index) floats must be displayed after all other stuff. 52 | 53 | - is sometimes incorrect. 54 | 55 | - more font style synthesis in html2ppm. 56 | 57 | - add xml CDATA parsing 58 | 59 | Ideas 60 | ----- 61 | 62 | - vi mode. 63 | - vertical scroll bar 64 | - better Makefile (select modes) 65 | - add auto close buffer flag (for list mode) 66 | - improve dired (file commands, nicer display) 67 | - rethink mode specific commands -> add inheritance for all commands ? 68 | - shorter command types handling (suppress ESxxx and use one type per arg) 69 | -------------------------------------------------------------------------------- /qestyles.h: -------------------------------------------------------------------------------- 1 | /* root style, must be complete */ 2 | STYLE_DEF(QE_STYLE_DEFAULT, "default", 3 | QERGB(0xf8, 0xd8, 0xb0), QERGB(0x00, 0x00, 0x00), 4 | QE_FAMILY_FIXED, 12) 5 | 6 | /* system styles */ 7 | STYLE_DEF(QE_STYLE_MODE_LINE, "mode-line", 8 | QERGB(0x00, 0x00, 0x00), QERGB(0xe0, 0xe0, 0xe0), 9 | 0, 0) 10 | STYLE_DEF(QE_STYLE_MINIBUF, "minibuf", 11 | QERGB(0xff, 0xff, 0x00), COLOR_TRANSPARENT, 12 | 0, 0) 13 | STYLE_DEF(QE_STYLE_STATUS, "status", 14 | QERGB(0xff, 0xff, 0x00), COLOR_TRANSPARENT, 15 | 0, 0) 16 | 17 | /* default style for HTML/CSS2 pages */ 18 | STYLE_DEF(QE_STYLE_CSS_DEFAULT, "css-default", 19 | QERGB(0x00, 0x00, 0x00), QERGB(0xbb, 0xbb, 0xbb), 20 | QE_FAMILY_SERIF, 12) 21 | 22 | /* coloring styles */ 23 | STYLE_DEF(QE_STYLE_HIGHLIGHT, "highlight", 24 | QERGB(0x00, 0x00, 0x00), QERGB(0xf8, 0xd8, 0xb0), 25 | 0, 0) 26 | STYLE_DEF(QE_STYLE_SELECTION, "selection", 27 | QERGB(0xff, 0xff, 0xff), QERGB(0x00, 0x00, 0xff), 28 | 0, 0) 29 | STYLE_DEF(QE_STYLE_COMMENT, "comment", 30 | QERGB(0xf8, 0x44, 0x00), COLOR_TRANSPARENT, 31 | 0, 0) 32 | STYLE_DEF(QE_STYLE_PREPROCESS, "preprocess", 33 | QERGB(0x00, 0xff, 0xff), COLOR_TRANSPARENT, 34 | 0, 0) 35 | STYLE_DEF(QE_STYLE_STRING, "string", 36 | QERGB(0xf8, 0xa0, 0x78), COLOR_TRANSPARENT, 37 | 0, 0) 38 | STYLE_DEF(QE_STYLE_KEYWORD, "keyword", 39 | QERGB(0x00, 0xff, 0xff), COLOR_TRANSPARENT, 40 | 0, 0) 41 | STYLE_DEF(QE_STYLE_FUNCTION, "function", 42 | QERGB(0x80, 0xcc, 0xf0), COLOR_TRANSPARENT, 43 | 0, 0) 44 | STYLE_DEF(QE_STYLE_VARIABLE, "variable", 45 | QERGB(0xe8, 0xdc, 0x80), COLOR_TRANSPARENT, 46 | 0, 0) 47 | STYLE_DEF(QE_STYLE_TYPE, "type", 48 | QERGB(0x98, 0xf8, 0x98), COLOR_TRANSPARENT, 49 | 0, 0) 50 | STYLE_DEF(QE_STYLE_TAG, "tag", 51 | QERGB(0x00, 0xff, 0xff), COLOR_TRANSPARENT, 52 | 0, 0) 53 | STYLE_DEF(QE_STYLE_CSS, "css", 54 | QERGB(0x98, 0xf8, 0x98), COLOR_TRANSPARENT, 55 | 0, 0) 56 | -------------------------------------------------------------------------------- /qfribidi.h: -------------------------------------------------------------------------------- 1 | 2 | typedef int FriBidiChar; 3 | 4 | typedef enum { 5 | /* do not change the order of these constants since 'property_val' 6 | depends on them */ 7 | FRIBIDI_TYPE_LTR, /* Strong left to right */ 8 | FRIBIDI_TYPE_RTL, /* Right to left characters */ 9 | FRIBIDI_TYPE_WL, /* Weak left to right */ 10 | FRIBIDI_TYPE_WR, /* Weak right to left */ 11 | FRIBIDI_TYPE_EN, /* European digit */ 12 | FRIBIDI_TYPE_ES, /* European number separator */ 13 | FRIBIDI_TYPE_ET, /* European number terminator */ 14 | FRIBIDI_TYPE_AN, /* Arabic digit */ 15 | FRIBIDI_TYPE_CS, /* Common Separator */ 16 | FRIBIDI_TYPE_BS, /* Block separator */ 17 | FRIBIDI_TYPE_SS, /* Segment separator */ 18 | FRIBIDI_TYPE_WS, /* Whitespace */ 19 | FRIBIDI_TYPE_AL, /* Arabic characters */ 20 | FRIBIDI_TYPE_NSM, /* Non spacing mark */ 21 | FRIBIDI_TYPE_BN, 22 | FRIBIDI_TYPE_ON, /* Other Neutral */ 23 | FRIBIDI_TYPE_LRE, /* Left-To-Right embedding */ 24 | FRIBIDI_TYPE_RLE, /* Right-To-Left embedding */ 25 | FRIBIDI_TYPE_PDF, /* Pop directional override */ 26 | FRIBIDI_TYPE_LRO, /* Left-To-Right override */ 27 | FRIBIDI_TYPE_RLO, /* Right-To-Left override */ 28 | 29 | /* The following are only used internally */ 30 | FRIBIDI_TYPE_SOT, 31 | FRIBIDI_TYPE_EOT, 32 | FRIBIDI_TYPE_N, 33 | FRIBIDI_TYPE_E, 34 | FRIBIDI_TYPE_CTL, /* Control units */ 35 | FRIBIDI_TYPE_EO, /* Control units */ 36 | FRIBIDI_TYPE_NULL, /* type record is to be deleted */ 37 | FRIBIDI_TYPE_L = FRIBIDI_TYPE_LTR, 38 | FRIBIDI_TYPE_R = FRIBIDI_TYPE_RTL, 39 | FRIBIDI_TYPE_CM = FRIBIDI_TYPE_ON + 2, 40 | } FriBidiCharType; 41 | 42 | /*====================================================================== 43 | // Typedef for the run-length list. 44 | //----------------------------------------------------------------------*/ 45 | typedef struct _TypeLink { 46 | FriBidiCharType type; 47 | int pos; 48 | int len; 49 | int level; 50 | } TypeLink; 51 | 52 | FriBidiCharType fribidi_get_type(FriBidiChar ch); 53 | FriBidiCharType fribidi_get_type_test(FriBidiChar ch); 54 | FriBidiChar fribidi_get_mirror_char(FriBidiChar ch); 55 | 56 | void fribidi_analyse_string(TypeLink * type_rl_list, 57 | FriBidiCharType * pbase_dir, 58 | int *pmax_level); 59 | 60 | -------------------------------------------------------------------------------- /cutils.h: -------------------------------------------------------------------------------- 1 | #ifndef CUTILS_H 2 | #define CUTILS_H 3 | 4 | #include 5 | 6 | int strstart(const char *str, const char *val, const char **ptr); 7 | int stristart(const char *str, const char *val, const char **ptr); 8 | void pstrcpy(char *buf, int buf_size, const char *str); 9 | char *pstrcat(char *buf, int buf_size, const char *s); 10 | 11 | /* simple dynamic strings wrappers. The strings are always terminated 12 | by zero except if they are empty. */ 13 | 14 | typedef struct QString { 15 | unsigned char *data; 16 | int len; /* string length excluding trailing '\0' */ 17 | } QString; 18 | 19 | static inline void qstrinit(QString *q) 20 | { 21 | q->data = NULL; 22 | q->len = 0; 23 | } 24 | 25 | static inline void qstrfree(QString *q) 26 | { 27 | free(q->data); 28 | } 29 | 30 | int qmemcat(QString *q, const unsigned char *data1, int len1); 31 | int qstrcat(QString *q, const char *str); 32 | int qprintf(QString *q, const char *fmt, ...); 33 | 34 | /* Double linked lists. Same api as the linux kernel */ 35 | 36 | struct list_head { 37 | struct list_head *next, *prev; 38 | }; 39 | 40 | static inline int list_empty(struct list_head *head) 41 | { 42 | return head->next == head; 43 | } 44 | 45 | static inline void __list_add(struct list_head *elem, 46 | struct list_head *prev, struct list_head *next) 47 | { 48 | next->prev = elem; 49 | elem->next = next; 50 | prev->next = elem; 51 | elem->prev = prev; 52 | } 53 | 54 | static inline void __list_del(struct list_head *prev, struct list_head *next) 55 | { 56 | prev->next = next; 57 | next->prev = prev; 58 | } 59 | 60 | #define LIST_HEAD(name) struct list_head name = { &name, &name } 61 | 62 | /* add at the head */ 63 | #define list_add(elem, head) \ 64 | __list_add((struct list_head *)elem, head, (head)->next); 65 | 66 | /* add at tail */ 67 | #define list_add_tail(elem, head) \ 68 | __list_add((struct list_head *)elem, (head)->prev, head) 69 | 70 | /* delete */ 71 | #define list_del(elem) __list_del(((struct list_head *)elem)->prev, \ 72 | ((struct list_head *)elem)->next) 73 | 74 | #define list_for_each(elem, head) \ 75 | for (elem = (void *)(head)->next; elem != (void *)(head); elem = elem->next) 76 | 77 | #define list_for_each_safe(elem, elem1, head) \ 78 | for (elem = (void *)(head)->next, elem1 = elem->next; elem != (void *)(head); \ 79 | elem = elem1, elem1 = elem->next) 80 | 81 | #define list_for_each_prev(elem, head) \ 82 | for (elem = (void *)(head)->prev; elem != (void *)(head); elem = elem->prev) 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /xterm-146-dw-patch: -------------------------------------------------------------------------------- 1 | --- xterm-146/fontutils.c Mon Sep 11 11:35:21 2000 2 | +++ xterm-146-w/fontutils.c Tue Oct 24 01:07:37 2000 3 | @@ -469,8 +469,17 @@ 4 | static int 5 | is_fixed_font(XFontStruct *fs) 6 | { 7 | - return (fs->min_bounds.width == fs->max_bounds.width 8 | - && fs->min_bounds.width == fs->min_bounds.width); 9 | + return (fs->min_bounds.width == fs->max_bounds.width); 10 | +} 11 | + 12 | +/* 13 | + * Check if the font looks like a double width font (i.e. contains 14 | + * characters of width X and 2X 15 | + */ 16 | +static int 17 | +is_double_width_font(XFontStruct *fs) 18 | +{ 19 | + return (2 * fs->min_bounds.width == fs->max_bounds.width); 20 | } 21 | 22 | #define EmptyFont(fs) ((fs)->ascent + (fs)->descent == 0 \ 23 | @@ -518,7 +527,7 @@ 24 | if (!(nfs = XLoadQueryFont (screen->display, nfontname))) goto bad; 25 | if (EmptyFont(nfs)) 26 | goto bad; /* can't use a 0-sized font */ 27 | - 28 | + 29 | 30 | strcpy(normal, nfontname); 31 | if (bfontname == 0) { 32 | @@ -550,7 +559,7 @@ 33 | * fonts for 9x18 and 6x13. 34 | */ 35 | if_OPT_WIDE_CHARS(screen, { 36 | - if (wfontname == 0) { 37 | + if (wfontname == 0 && !is_double_width_font(nfs)) { 38 | fp = get_font_name_props(screen->display, nfs, normal); 39 | if (fp != 0) { 40 | wfontname = wide_font_name(fp); 41 | @@ -593,13 +602,20 @@ 42 | } 43 | } 44 | 45 | + 46 | + /* 47 | + * We accept that the normal font is a double width font (such 48 | + * as the GNU unifont, so that we do not need to use the -fw 49 | + * option 50 | + */ 51 | + if (is_double_width_font(nfs)) { 52 | + wfs = nfs; 53 | + } else if (!is_fixed_font(nfs) 54 | + || !is_fixed_font(bfs) 55 | + || nfs->max_bounds.width != bfs->max_bounds.width) { 56 | /* 57 | * Normal/bold fonts should be the same width. Also, the min/max 58 | - * values should be the same. 59 | - */ 60 | - if (!is_fixed_font(nfs) 61 | - || !is_fixed_font(bfs) 62 | - || nfs->max_bounds.width != bfs->max_bounds.width) { 63 | + * values should be the same. */ 64 | TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 65 | nfs->min_bounds.width, 66 | nfs->max_bounds.width, 67 | @@ -770,7 +786,11 @@ 68 | { 69 | int i, j, width, height; 70 | 71 | - win->f_width = (font->max_bounds.width); 72 | + if (is_double_width_font(font)) { 73 | + win->f_width = (font->min_bounds.width); 74 | + } else { 75 | + win->f_width = (font->max_bounds.width); 76 | + } 77 | win->f_height = (font->ascent + font->descent); 78 | i = 2 * screen->border + sbwidth; 79 | j = 2 * screen->border; 80 | -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * List mode for QEmacs. 3 | * Copyright (c) 2001, 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | static int list_get_colorized_line(EditState *s, unsigned int *buf, int buf_size, 22 | int offset, int line_num) 23 | { 24 | QEmacsState *qs = s->qe_state; 25 | int len; 26 | int offset1; 27 | 28 | offset1 = offset; 29 | len = eb_get_line(s->b, buf, buf_size, &offset1); 30 | 31 | if (((qs->active_window == s) || s->force_highlight) && 32 | s->offset >= offset && s->offset < offset1) { 33 | /* highlight the line if the cursor is inside */ 34 | set_color(buf, len, QE_STYLE_HIGHLIGHT); 35 | } else if (buf[0] == '*') { 36 | /* selection */ 37 | set_color(buf, len, QE_STYLE_SELECTION); 38 | } 39 | return len; 40 | } 41 | 42 | /* get current position (index) in list */ 43 | int list_get_pos(EditState *s) 44 | { 45 | int line, col; 46 | eb_get_pos(s->b, &line, &col, s->offset); 47 | return line; 48 | } 49 | 50 | /* get current offset of the line in list */ 51 | int list_get_offset(EditState *s) 52 | { 53 | int line, col; 54 | eb_get_pos(s->b, &line, &col, s->offset); 55 | return eb_goto_pos(s->b, line, 0); 56 | } 57 | 58 | void list_toggle_selection(EditState *s) 59 | { 60 | int offset; 61 | unsigned char ch; 62 | 63 | offset = list_get_offset(s); 64 | 65 | eb_read(s->b, offset , &ch, 1); 66 | if (ch == ' ') 67 | ch = '*'; 68 | else 69 | ch = ' '; 70 | eb_write(s->b, offset , &ch, 1); 71 | 72 | text_move_up_down(s, 1); 73 | } 74 | 75 | static int list_mode_init(EditState *s, ModeSavedData *saved_data) 76 | { 77 | s->wrap = WRAP_TRUNCATE; 78 | s->interactive = 1; 79 | s->get_colorized_line_func = list_get_colorized_line; 80 | return 0; 81 | } 82 | 83 | static void list_mode_close(EditState *s) 84 | { 85 | } 86 | 87 | ModeDef list_mode; 88 | 89 | static int list_init(void) 90 | { 91 | memcpy(&list_mode, &text_mode, sizeof(ModeDef)); 92 | list_mode.mode_probe = NULL; 93 | list_mode.mode_init = list_mode_init; 94 | list_mode.mode_close = list_mode_close; 95 | list_mode.mode_flags = MODEF_NOCMD; 96 | 97 | qe_register_mode(&list_mode); 98 | 99 | return 0; 100 | } 101 | 102 | qe_module_init(list_init); 103 | -------------------------------------------------------------------------------- /libfbf.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBFBF_H 2 | #define LIBFBF_Hx 3 | 4 | typedef struct { 5 | unsigned int magic; 6 | unsigned int version; 7 | unsigned int nb_glyphs; 8 | unsigned int compressed_segment_size; 9 | unsigned int flags; 10 | unsigned short max_width; 11 | unsigned short max_height; 12 | unsigned short x_res; 13 | unsigned short y_res; 14 | unsigned short pt_size; 15 | unsigned short ascent; 16 | unsigned short descent; 17 | unsigned short line_height; 18 | short underline_position; 19 | unsigned short underline_thickness; 20 | unsigned short nb_segments; 21 | unsigned char family_type; 22 | unsigned char dummy; /* align */ 23 | } UnifontHeader; 24 | 25 | #define UNIFONT_MAGIC (('U' << 24) | ('N' << 16) | ('F' << 8) | ('T')) 26 | 27 | /* interval compression model parameters */ 28 | 29 | #define NB_CTX ((1 << 12) * 3 * 3) 30 | #define NB_CTX1 (1 << 10) 31 | 32 | #define MAXDIST 4 33 | 34 | #define MAXWIDTH 128 35 | #define MAXHEIGHT 128 36 | #define MAXWRAP ((MAXWIDTH+7)/8) 37 | 38 | #define WRAP (MAXWIDTH + 2 * MAXDIST) 39 | 40 | /* arith coder parameters */ 41 | #define RANGE_MIN (1 << 10) 42 | 43 | /* flags */ 44 | #define UF_FLAG_HANGUL 0x0001 /* use ad hoc hangul compression */ 45 | 46 | /* family type */ 47 | #define UF_FAMILY_FIXED 0 48 | #define UF_FAMILY_SERIF 1 49 | #define UF_FAMILY_SANS 2 50 | 51 | #define JOHAB_BASE 0x20000 52 | 53 | /* segment cache */ 54 | typedef struct { 55 | short w, h; 56 | short x, y, xincr; 57 | unsigned char *bitmap; 58 | } GlyphEntry; 59 | 60 | struct UniFontData; 61 | 62 | typedef struct UniFontData UniFontData; 63 | 64 | #define CSEG_CACHE_SIZE 8 65 | 66 | typedef struct SegData { 67 | unsigned int start; 68 | unsigned short glyph; 69 | unsigned short size; 70 | } SegData; 71 | 72 | struct UniFontData { 73 | struct UniFontData *next_font; /* can be used by the user to link 74 | to next font */ 75 | int nb_glyphs; /* real number of glyphs */ 76 | int nb_glyphs_total; /* total number, including algorithmically 77 | generated ones */ 78 | unsigned int flags; 79 | int compressed_segment_size; 80 | int max_width, max_height; /* maximum dimensions of bitmaps */ 81 | int x_res, y_res, pt_size; 82 | int ascent, descent, line_height; 83 | int underline_position; /* in 64th pixel */ 84 | int underline_thickness; /* in 64th pixel */ 85 | char family_name[64]; 86 | int family_type; 87 | /* compressed segments offsets */ 88 | int nb_csegs; 89 | int *csegs_offsets; 90 | int *msegs_offsets; 91 | /* compressed segment cache */ 92 | struct GlyphSegment *cseg_cache[CSEG_CACHE_SIZE]; 93 | 94 | /* segments */ 95 | /* XXX: allocation */ 96 | int nb_segs; 97 | SegData *seg_table; 98 | 99 | /* memory functions */ 100 | void *mem_opaque; 101 | void *(*fbf_malloc)(void *mem_opaque, int size); 102 | void (*fbf_free)(void *mem_opaque, void *ptr); 103 | 104 | /* file input handlings */ 105 | void *infile; 106 | int (*fbf_seek)(void *infile, long pos); 107 | int (*fbf_read)(void *infile, unsigned char *buf, int len); 108 | int (*fbf_getc)(void *infile); 109 | 110 | /* bit buffer handling */ 111 | int bitbuf; 112 | int bitcnt; 113 | unsigned char ctx1[NB_CTX1]; 114 | /* arithmetic decoder */ 115 | unsigned int alow, arange, adata; 116 | 117 | /* temporary bitmap for composite glyph decoding */ 118 | unsigned char tmp_buffer[MAXWRAP * MAXHEIGHT]; 119 | GlyphEntry tmp_glyph_entry; 120 | }; 121 | 122 | typedef struct GlyphSegment { 123 | int first_glyph; 124 | int nb_glyphs; 125 | int use_count; 126 | unsigned char *bitmap_table; 127 | GlyphEntry metrics[1]; 128 | } GlyphSegment; 129 | 130 | int fbf_load_font(UniFontData *uf); 131 | void fbf_free_font(UniFontData *uf); 132 | 133 | int fbf_unicode_to_glyph(UniFontData *uf, int code); 134 | int fbf_decode_glyph(UniFontData *uf, 135 | GlyphEntry **glyph_entry_ptr, 136 | int index); 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /indic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Indic algorithms for QEmacs. 3 | * 4 | * Copyright (c) 2000 Fabrice Bellard. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | #include "qe.h" 21 | #include "qfribidi.h" 22 | 23 | #define VIRAMA 0x94d 24 | #define RA 0x930 25 | #define RRA 0x931 26 | #define ZERO_WIDTH_JOINER 0x200d 27 | 28 | /* private unicode extensions */ 29 | #define DEAD_CONSONANT_OFFSET 0x10000 30 | #define HALF_OFFSET 0xe000 31 | 32 | #define RA_SUP 0xe97e 33 | #define RA_SUB 0xe97f 34 | #define RRA_HALF 0xe97d 35 | #define RA_DEAD (RA + DEAD_CONSONANT_OFFSET) 36 | 37 | #if 0 38 | static int is_vowel_sign (unsigned int i) 39 | { 40 | return (i >= 0x93E && i <= 0x94c) || (i >= 0x962 && i <= 0x963); 41 | } 42 | #endif 43 | 44 | static int is_consonant (unsigned int i) 45 | { 46 | return (i >= 0x915 && i <= 0x939) || (i >= 0x958 && i <= 0x95f); 47 | } 48 | 49 | static int is_ind_vowel (unsigned int i) 50 | { 51 | return (i >= 0x905 && i <= 0x914); 52 | } 53 | 54 | static int is_dead_consonant(unsigned int i) 55 | { 56 | return (i >= DEAD_CONSONANT_OFFSET && i <= DEAD_CONSONANT_OFFSET + 0x7f); 57 | } 58 | 59 | /* always returns a smaller buffer */ 60 | int devanagari_log2vis(unsigned int *str, unsigned int *ctog, int len) 61 | { 62 | int i, len1, cc, j, k, c; 63 | unsigned int *q, buf[len]; 64 | 65 | /* Rule 1 : dead consonant rule */ 66 | q = buf; 67 | len1 = len - 1; 68 | for(i=0;idisp_width = 8; 30 | s->hex_mode = 1; 31 | s->unihex_mode = 1; 32 | s->hex_nibble = 0; 33 | s->wrap = WRAP_TRUNCATE; 34 | return 0; 35 | } 36 | 37 | static int unihex_backward_offset(EditState *s, int offset) 38 | { 39 | int pos; 40 | pos = eb_get_char_offset(s->b, offset); 41 | pos = align(pos, s->disp_width); 42 | return eb_goto_char(s->b, pos); 43 | } 44 | 45 | static int unihex_display(EditState *s, DisplayState *ds, int offset) 46 | { 47 | int j, len, eof; 48 | int offset1; 49 | unsigned int b; 50 | unsigned int buf[LINE_MAX_SIZE]; 51 | unsigned int pos[LINE_MAX_SIZE]; 52 | 53 | eof = 0; 54 | display_bol(ds); 55 | 56 | display_printf(ds, -1, -1, "%08x ", offset); 57 | 58 | len = 0; 59 | for(j=0;jdisp_width;j++) { 60 | if (offset < s->b->total_size) { 61 | b = eb_nextc(s->b, offset, &offset1); 62 | pos[len] = offset; 63 | buf[len] = b; 64 | len++; 65 | offset = offset1; 66 | } 67 | } 68 | pos[len] = offset; 69 | 70 | for(j=0;jdisp_width;j++) { 71 | display_char(ds, -1, -1, ' '); 72 | if (j < len) { 73 | display_printhex(ds, pos[j], pos[j+1], buf[j], 4); 74 | } else { 75 | if (!eof) { 76 | eof = 1; 77 | display_printf(ds, pos[j], pos[j] + 1, " "); 78 | } else { 79 | display_printf(ds, -1, -1, " "); 80 | } 81 | } 82 | if ((j & 7) == 7) 83 | display_char(ds, -1, -1, ' '); 84 | } 85 | display_char(ds, -1, -1, ' '); 86 | display_char(ds, -1, -1, ' '); 87 | 88 | for(j=0;jdisp_width;j++) { 89 | if (j < len) { 90 | b = buf[j]; 91 | if (b < ' ' || b == 127) 92 | b = '.'; 93 | display_char(ds, pos[j], pos[j+1], b); 94 | } else { 95 | b = ' '; 96 | if (!eof) { 97 | eof = 1; 98 | display_char(ds, pos[j], pos[j] + 1, b); 99 | } else { 100 | display_char(ds, -1, -1, b); 101 | } 102 | } 103 | } 104 | display_eol(ds, -1, -1); 105 | 106 | if (len >= s->disp_width) 107 | return offset; 108 | else 109 | return -1; 110 | } 111 | 112 | 113 | void unihex_move_bol(EditState *s) 114 | { 115 | int pos; 116 | 117 | pos = eb_get_char_offset(s->b, s->offset); 118 | pos = align(pos, s->disp_width); 119 | s->offset = eb_goto_char(s->b, pos); 120 | } 121 | 122 | void unihex_move_eol(EditState *s) 123 | { 124 | int pos; 125 | 126 | pos = eb_get_char_offset(s->b, s->offset); 127 | 128 | pos = align(pos, s->disp_width) + s->disp_width - 1; 129 | 130 | s->offset = eb_goto_char(s->b, pos); 131 | } 132 | 133 | void unihex_move_left_right(EditState *s, int dir) 134 | { 135 | if (dir > 0) { 136 | eb_nextc(s->b, s->offset, &s->offset); 137 | } else { 138 | eb_prevc(s->b, s->offset, &s->offset); 139 | } 140 | } 141 | 142 | void unihex_move_up_down(EditState *s, int dir) 143 | { 144 | int pos; 145 | 146 | pos = eb_get_char_offset(s->b, s->offset); 147 | 148 | pos += dir * s->disp_width; 149 | 150 | s->offset = eb_goto_char(s->b, pos); 151 | } 152 | 153 | ModeDef unihex_mode = { 154 | "unihex", 155 | instance_size: 0, 156 | mode_probe: NULL, 157 | mode_init: unihex_mode_init, 158 | mode_close: text_mode_close, 159 | text_display: unihex_display, 160 | text_backward_offset: unihex_backward_offset, 161 | 162 | move_up_down: unihex_move_up_down, 163 | move_left_right: unihex_move_left_right, 164 | move_bol: unihex_move_bol, 165 | move_eol: unihex_move_eol, 166 | scroll_up_down: text_scroll_up_down, 167 | write_char: hex_write_char, 168 | mouse_goto: text_mouse_goto, 169 | }; 170 | 171 | 172 | static int unihex_init(void) 173 | { 174 | /* first register mode(s) */ 175 | qe_register_mode(&unihex_mode); 176 | 177 | /* additionnal mode specific keys */ 178 | qe_register_binding(KEY_CTRL_LEFT, "decrease-width", "unihex"); 179 | qe_register_binding(KEY_CTRL_RIGHT, "increase-width", "unihex"); 180 | qe_register_binding(KEY_CTRL('i'), "toggle-hex", "unihex"); 181 | return 0; 182 | } 183 | 184 | qe_module_init(unihex_init); 185 | -------------------------------------------------------------------------------- /cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Various simple C utilities 3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "cutils.h" 26 | 27 | #if !defined(CONFIG_NOCUTILS) 28 | /** 29 | * Return TRUE if val is a prefix of str. If it returns TRUE, ptr is 30 | * set to the next character in 'str' after the prefix. 31 | * 32 | * @param str input string 33 | * @param val prefix to test 34 | * @param ptr updated after the prefix in str in there is a match 35 | * @return TRUE if there is a match 36 | */ 37 | int strstart(const char *str, const char *val, const char **ptr) 38 | { 39 | const char *p, *q; 40 | p = str; 41 | q = val; 42 | while (*q != '\0') { 43 | if (*p != *q) 44 | return 0; 45 | p++; 46 | q++; 47 | } 48 | if (ptr) 49 | *ptr = p; 50 | return 1; 51 | } 52 | 53 | /** 54 | * Return TRUE if val is a prefix of str (case independent). If it 55 | * returns TRUE, ptr is set to the next character in 'str' after the 56 | * prefix. 57 | * 58 | * @param str input string 59 | * @param val prefix to test 60 | * @param ptr updated after the prefix in str in there is a match 61 | * @return TRUE if there is a match */ 62 | int stristart(const char *str, const char *val, const char **ptr) 63 | { 64 | const char *p, *q; 65 | p = str; 66 | q = val; 67 | while (*q != '\0') { 68 | if (toupper(*(unsigned char *)p) != toupper(*(unsigned char *)q)) 69 | return 0; 70 | p++; 71 | q++; 72 | } 73 | if (ptr) 74 | *ptr = p; 75 | return 1; 76 | } 77 | 78 | /** 79 | * Copy the string str to buf. If str length is bigger than buf_size - 80 | * 1 then it is clamped to buf_size - 1. 81 | * NOTE: this function does what strncpy should have done to be 82 | * useful. NEVER use strncpy. 83 | * 84 | * @param buf destination buffer 85 | * @param buf_size size of destination buffer 86 | * @param str source string 87 | */ 88 | void pstrcpy(char *buf, int buf_size, const char *str) 89 | { 90 | int c; 91 | char *q = buf; 92 | 93 | if (buf_size <= 0) 94 | return; 95 | 96 | for(;;) { 97 | c = *str++; 98 | if (c == 0 || q >= buf + buf_size - 1) 99 | break; 100 | *q++ = c; 101 | } 102 | *q = '\0'; 103 | } 104 | 105 | /* strcat and truncate. */ 106 | char *pstrcat(char *buf, int buf_size, const char *s) 107 | { 108 | int len; 109 | len = strlen(buf); 110 | if (len < buf_size) 111 | pstrcpy(buf + len, buf_size - len, s); 112 | return buf; 113 | } 114 | 115 | #endif 116 | 117 | /** 118 | * Add a memory region to a dynamic string. In case of allocation 119 | * failure, the data is not added. The dynamic string is guaranted to 120 | * be 0 terminated, although it can be longer if it contains zeros. 121 | * 122 | * @return 0 if OK, -1 if allocation error. 123 | */ 124 | int qmemcat(QString *q, const unsigned char *data1, int len1) 125 | { 126 | int new_len, len, alloc_size; 127 | unsigned char *data; 128 | 129 | data = q->data; 130 | len = q->len; 131 | new_len = len + len1; 132 | /* see if we got a new power of two */ 133 | /* NOTE: we got this trick from the excellent 'links' browser */ 134 | if ((len ^ new_len) >= len) { 135 | /* find immediately bigger 2^n - 1 */ 136 | alloc_size = new_len; 137 | alloc_size |= (alloc_size >> 1); 138 | alloc_size |= (alloc_size >> 2); 139 | alloc_size |= (alloc_size >> 4); 140 | alloc_size |= (alloc_size >> 8); 141 | alloc_size |= (alloc_size >> 16); 142 | /* allocate one more byte for end of string marker */ 143 | data = realloc(data, alloc_size + 1); 144 | if (!data) 145 | return -1; 146 | q->data = data; 147 | } 148 | memcpy(data + len, data1, len1); 149 | data[new_len] = '\0'; /* we force a trailing '\0' */ 150 | q->len = new_len; 151 | return 0; 152 | } 153 | 154 | /* 155 | * add a string to a dynamic string 156 | */ 157 | int qstrcat(QString *q, const char *str) 158 | { 159 | return qmemcat(q, (const unsigned char *)str, strlen(str)); 160 | } 161 | 162 | /* XXX: we use a fixed size buffer */ 163 | int qprintf(QString *q, const char *fmt, ...) 164 | { 165 | char buf[4096]; 166 | va_list ap; 167 | int len, ret; 168 | 169 | va_start(ap, fmt); 170 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 171 | /* avoid problems for non C99 snprintf() which can return -1 if overflow */ 172 | if (len < 0) 173 | len = strlen(buf); 174 | ret = qmemcat(q, (const unsigned char *)buf, len); 175 | va_end(ap); 176 | return ret; 177 | } 178 | 179 | -------------------------------------------------------------------------------- /mpeg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MPEG mode for QEmacs. 3 | * Copyright (c) 2001 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | #define SEQ_END_CODE 0x000001b7 22 | #define SEQ_START_CODE 0x000001b3 23 | #define GOP_START_CODE 0x000001b8 24 | #define PICTURE_START_CODE 0x00000100 25 | #define SLICE_MIN_START_CODE 0x00000101 26 | #define SLICE_MAX_START_CODE 0x000001af 27 | #define EXT_START_CODE 0x000001b5 28 | #define USER_START_CODE 0x000001b2 29 | 30 | #define PACK_START_CODE 0x000001ba 31 | #define SYSTEM_HEADER_START_CODE 0x000001bb 32 | #define ISO_11172_END_CODE 0x000001b9 33 | 34 | static int mpeg_display(EditState *s, DisplayState *ds, int offset) 35 | { 36 | unsigned int startcode; 37 | int ret, badchars, offset_start; 38 | unsigned char buf[4]; 39 | 40 | /* search start code */ 41 | 42 | badchars = 0; 43 | 44 | display_bol(ds); 45 | display_printf(ds, -1, -1, "%08x:", offset); 46 | for(;;) { 47 | ret = eb_read(s->b, offset, buf, 4); 48 | if (ret == 0) { 49 | if (badchars) 50 | display_eol(ds, -1, -1); 51 | goto the_end; 52 | } 53 | 54 | if (ret == 4) { 55 | startcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; 56 | if ((startcode & 0xffffff00) == 0x00000100) { 57 | if (badchars) { 58 | display_eol(ds, -1, -1); 59 | display_bol(ds); 60 | display_printf(ds, -1, -1, "%08x:", offset); 61 | } 62 | break; 63 | } 64 | } 65 | /* display unknown chars */ 66 | display_printf(ds, -1, -1, " ["); 67 | display_printhex(ds, offset, offset + 1, buf[0], 2); 68 | display_printf(ds, -1, -1, "]"); 69 | offset++; 70 | if (++badchars == 8) { 71 | badchars = 0; 72 | display_eol(ds, -1, -1); 73 | goto the_end; 74 | } 75 | } 76 | offset_start = offset; 77 | offset += 4; 78 | display_printf(ds, offset_start, offset, " [%08x] ", startcode); 79 | 80 | switch(startcode) { 81 | case SEQ_END_CODE: 82 | display_printf(ds, -1, -1, "SEQ_END"); 83 | break; 84 | case SEQ_START_CODE: 85 | display_printf(ds, -1, -1, "SEQUENCE"); 86 | break; 87 | case PICTURE_START_CODE: 88 | display_printf(ds, -1, -1, "PICTURE"); 89 | break; 90 | case GOP_START_CODE: 91 | display_printf(ds, -1, -1, "GOP"); 92 | break; 93 | case EXT_START_CODE: 94 | display_printf(ds, -1, -1, "EXT"); 95 | break; 96 | case PACK_START_CODE: 97 | display_printf(ds, -1, -1, "PACK"); 98 | break; 99 | case SYSTEM_HEADER_START_CODE: 100 | display_printf(ds, -1, -1, "SYSTEM"); 101 | break; 102 | default: 103 | if (startcode >= SLICE_MIN_START_CODE && 104 | startcode <= SLICE_MAX_START_CODE) { 105 | display_printf(ds, -1, -1, "SLICE %d", startcode & 0xff); 106 | } else { 107 | display_printf(ds, -1, -1, "UNKNOWN", startcode); 108 | } 109 | break; 110 | } 111 | 112 | display_eol(ds, -1, -1); 113 | the_end: 114 | return offset; 115 | } 116 | 117 | /* go to previous synchronization point */ 118 | static int mpeg_backward_offset(EditState *s, int offset) 119 | { 120 | unsigned char buf[4]; 121 | unsigned int startcode; 122 | int ret; 123 | 124 | for(;;) { 125 | if (offset <= 0) 126 | break; 127 | ret = eb_read(s->b, offset, buf, 4); 128 | if (ret != 4) 129 | break; 130 | startcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; 131 | if ((startcode & 0xffffff00) == 0x00000100) { 132 | break; 133 | } 134 | offset--; 135 | } 136 | return offset; 137 | } 138 | 139 | static int mpeg_mode_init(EditState *s, ModeSavedData *saved_data) 140 | { 141 | int ret; 142 | ret = text_mode_init(s, saved_data); 143 | if (ret) 144 | return ret; 145 | 146 | s->hex_mode = 1; 147 | s->hex_nibble = 0; 148 | s->wrap = WRAP_TRUNCATE; 149 | return 0; 150 | } 151 | 152 | static int mpeg_mode_probe(ModeProbeData *p) 153 | { 154 | if (p->buf_size >= 4 && 155 | p->buf[0] == 0x00 && 156 | p->buf[1] == 0x00 && 157 | p->buf[2] == 0x01 && 158 | p->buf[3] >= 0xa0) 159 | return 100; 160 | else 161 | return 0; 162 | } 163 | 164 | static ModeDef mpeg_mode = { 165 | "mpeg", 166 | mode_probe: mpeg_mode_probe, 167 | mode_init: mpeg_mode_init, 168 | mode_close: NULL, 169 | text_display: mpeg_display, 170 | text_backward_offset: mpeg_backward_offset, 171 | write_char: hex_write_char, 172 | }; 173 | 174 | static int mpeg_init(void) 175 | { 176 | qe_register_mode(&mpeg_mode); 177 | return 0; 178 | } 179 | 180 | 181 | qe_module_init(mpeg_init); 182 | -------------------------------------------------------------------------------- /bufed.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Buffer editor mode for QEmacs. 3 | * Copyright (c) 2001, 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | typedef struct BufedState { 22 | StringArray items; 23 | } BufedState; 24 | 25 | ModeDef bufed_mode; 26 | 27 | static void build_bufed_list(EditState *s) 28 | { 29 | QEmacsState *qs = s->qe_state; 30 | EditBuffer *b; 31 | BufedState *hs; 32 | int i; 33 | 34 | hs = s->mode_data; 35 | 36 | free_strings(&hs->items); 37 | for(b = qs->first_buffer; b != NULL; b = b->next) { 38 | if (!(b->flags & BF_SYSTEM)) 39 | add_string(&hs->items, b->name); 40 | } 41 | 42 | /* build buffer */ 43 | b = s->b; 44 | eb_delete(b, 0, b->total_size); 45 | for(i=0;iitems.nb_items;i++) { 46 | eb_printf(b, " %s", hs->items.items[i]->str); 47 | if (i != hs->items.nb_items - 1) 48 | eb_printf(b, "\n"); 49 | } 50 | } 51 | 52 | static void bufed_select(EditState *s) 53 | { 54 | BufedState *bs = s->mode_data; 55 | StringItem *item; 56 | EditBuffer *b; 57 | EditState *e; 58 | int index; 59 | 60 | index = list_get_pos(s); 61 | if (index < 0 || index >= bs->items.nb_items) 62 | return; 63 | item = bs->items.items[index]; 64 | b = eb_find(item->str); 65 | if (!b) 66 | return; 67 | e = find_window_right(s); 68 | if (!e) 69 | return; 70 | /* delete dired window */ 71 | do_delete_window(s, 1); 72 | switch_to_buffer(e, b); 73 | } 74 | 75 | /* iterate 'func_item' to selected items. If no selected items, then 76 | use current item */ 77 | void string_selection_iterate(StringArray *cs, 78 | int current_index, 79 | void (*func_item)(void *, StringItem *), 80 | void *opaque) 81 | { 82 | StringItem *item; 83 | int count, i; 84 | 85 | count = 0; 86 | for(i=0;inb_items;i++) { 87 | item = cs->items[i]; 88 | if (item->selected) { 89 | func_item(opaque, item); 90 | count++; 91 | } 92 | } 93 | 94 | /* if no item selected, then act on selected item */ 95 | if (count == 0 && 96 | current_index >=0 && current_index < cs->nb_items) { 97 | item = cs->items[current_index]; 98 | func_item(opaque, item); 99 | } 100 | } 101 | 102 | static void bufed_kill_item(void *opaque, StringItem *item) 103 | { 104 | EditState *s = opaque; 105 | do_kill_buffer(s, item->str); 106 | } 107 | 108 | static void bufed_kill_buffer(EditState *s) 109 | { 110 | BufedState *hs = s->mode_data; 111 | string_selection_iterate(&hs->items, list_get_pos(s), 112 | bufed_kill_item, s); 113 | build_bufed_list(s); 114 | } 115 | 116 | /* show a list of buffers */ 117 | static void do_list_buffers(EditState *s) 118 | { 119 | QEmacsState *qs = s->qe_state; 120 | BufedState *bs; 121 | EditBuffer *b; 122 | EditState *e; 123 | int width, i; 124 | 125 | /* XXX: must close this buffer when destroying window: add a 126 | special buffer flag to tell this */ 127 | b = eb_new("*bufed*", BF_READONLY | BF_SYSTEM); 128 | 129 | width = qs->width / 4; 130 | e = insert_window_left(b, width, WF_MODELINE); 131 | do_set_mode(e, &bufed_mode, NULL); 132 | 133 | bs = e->mode_data; 134 | 135 | /* if active buffer is found, go directly on it */ 136 | for(i=0;iitems.nb_items;i++) { 137 | if (!strcmp(bs->items.items[i]->str, s->b->name)) { 138 | e->offset = eb_goto_pos(e->b, i, 0); 139 | break; 140 | } 141 | } 142 | 143 | /* modify active window */ 144 | qs->active_window = e; 145 | } 146 | 147 | static int bufed_mode_init(EditState *s, ModeSavedData *saved_data) 148 | { 149 | list_mode.mode_init(s, saved_data); 150 | 151 | build_bufed_list(s); 152 | 153 | return 0; 154 | } 155 | 156 | static void bufed_mode_close(EditState *s) 157 | { 158 | BufedState *hs; 159 | hs = s->mode_data; 160 | free_strings(&hs->items); 161 | 162 | list_mode.mode_close(s); 163 | } 164 | 165 | /* specific bufed commands */ 166 | static CmdDef bufed_commands[] = { 167 | CMD0( KEY_RET, KEY_RIGHT, "bufed-select", bufed_select) 168 | CMD1( KEY_CTRL('g'), KEY_NONE, "delete-window", do_delete_window, 0) 169 | CMD0( ' ', KEY_CTRL('t'), "bufed-toggle_selection", list_toggle_selection) 170 | CMD0( KEY_F8, KEY_NONE, "bufed-kill-buffer", bufed_kill_buffer) 171 | CMD_DEF_END, 172 | }; 173 | 174 | static CmdDef bufed_global_commands[] = { 175 | CMD0( KEY_CTRLX(KEY_CTRL('b')), KEY_NONE, "list-buffers", do_list_buffers) 176 | CMD_DEF_END, 177 | }; 178 | 179 | static int bufed_init(void) 180 | { 181 | /* inherit from list mode */ 182 | memcpy(&bufed_mode, &list_mode, sizeof(ModeDef)); 183 | bufed_mode.name = "bufed"; 184 | bufed_mode.instance_size = sizeof(BufedState); 185 | bufed_mode.mode_init = bufed_mode_init; 186 | bufed_mode.mode_close = bufed_mode_close; 187 | 188 | /* first register mode */ 189 | qe_register_mode(&bufed_mode); 190 | 191 | qe_register_cmd_table(bufed_commands, "bufed"); 192 | qe_register_cmd_table(bufed_global_commands, NULL); 193 | 194 | return 0; 195 | } 196 | 197 | qe_module_init(bufed_init); 198 | -------------------------------------------------------------------------------- /cptoqe.c: -------------------------------------------------------------------------------- 1 | /* convert unicode cp pages to qe source code */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char *getline(char *buf, int buf_size, FILE *f) 8 | { 9 | char *str; 10 | int len; 11 | 12 | str = fgets(buf, buf_size, f); 13 | if (!str) 14 | return NULL; 15 | len = strlen(buf); 16 | if (len > 0 && buf[len - 1] == '\n') { 17 | buf[len - 1] = '\0'; 18 | } 19 | return str; 20 | } 21 | 22 | 23 | void handle_cp(FILE *f, const char *name) 24 | { 25 | char line[1024]; 26 | const char *p; 27 | int table[256]; 28 | int min_code, max_code, c1, c2, i, nb, j, c; 29 | char name1[256], *q; 30 | 31 | getline(line, sizeof(line), f); 32 | 33 | getline(line, sizeof(line), f); 34 | printf("static const char *aliases_%s[] = { %s, NULL };\n\n", name, line); 35 | for(i=0;i<256;i++) 36 | table[i] = i; 37 | nb = 0; 38 | for(;;) { 39 | if (!getline(line, sizeof(line), f)) 40 | break; 41 | if (!strcasecmp(line, "# compatibility")) 42 | break; 43 | if (line[0] == '\0' || line[0] == '#') 44 | continue; 45 | p = line; 46 | c1 = strtol(p, (char **)&p, 0); 47 | if (!isspace(*p)) 48 | continue; 49 | c2 = strtol(p, (char **)&p, 0); 50 | if (c1 >= 256) { 51 | fprintf(stderr, "%s: ERROR %d %d\n", name, c1, c2); 52 | continue; 53 | } 54 | table[c1] = c2; 55 | nb++; 56 | } 57 | if (table[10] != 10) 58 | fprintf(stderr, "%s: warning: newline is not preserved\n", name); 59 | 60 | min_code = 0x7fffffff; 61 | max_code = -1; 62 | for(i=0;i<256;i++) { 63 | if (table[i] != i) { 64 | if (i < min_code) 65 | min_code = i; 66 | if (i > max_code) 67 | max_code = i; 68 | } 69 | } 70 | // fprintf(stderr, "%s: %3d %02x %02x\n", name, nb, min_code, max_code); 71 | 72 | if (max_code != -1) { 73 | printf("static const unsigned short table_%s[%d] = {\n", 74 | name, max_code - min_code + 1); 75 | j = 0; 76 | for(i=min_code;i<=max_code;i++) { 77 | printf("0x%04x, ", table[i]); 78 | if ((j++ & 7) == 7) 79 | printf("\n"); 80 | } 81 | if ((j & 7) != 0) 82 | printf("\n"); 83 | printf("};\n\n"); 84 | } 85 | 86 | q = name1; 87 | for(p = name; *p != '\0'; p++) { 88 | c = *p; 89 | if (c == '_') 90 | c = '-'; 91 | *q++ = c; 92 | } 93 | *q = '\0'; 94 | 95 | printf("QECharset charset_%s = {\n" 96 | "\"%s\",\n" 97 | "aliases_%s,\n" 98 | "decode_8bit_init,\n" 99 | "NULL,\n" 100 | "encode_8bit,\n" 101 | "table_alloc: 1,\n" 102 | "min_char: %d,\n" 103 | "max_char: %d,\n" 104 | "private_table: table_%s,\n" 105 | "};\n\n", 106 | name, name1, name, 107 | min_code, max_code, name); 108 | } 109 | 110 | /* handle jis208 or jis212 table */ 111 | void handle_jis(FILE *f, int is_jis208) 112 | { 113 | int c1, c2, b1, b2, b1_max, b2_max, i, j, nb, n; 114 | int table[94*94]; 115 | int table_b2_max[94]; 116 | char line[1024]; 117 | const char *p; 118 | const char *name = is_jis208 ? "jis208" : "jis212"; 119 | 120 | memset(table, 0, sizeof(table)); 121 | memset(table_b2_max, 0, sizeof(table_b2_max)); 122 | b1_max = 0; 123 | b2_max = 0; 124 | nb = 0; 125 | for(;;) { 126 | if (!getline(line, sizeof(line), f)) 127 | break; 128 | if (line[0] == '\0' || line[0] == '#') 129 | continue; 130 | p = line; 131 | if (is_jis208) 132 | c1 = strtol(p, (char **)&p, 0); 133 | c1 = strtol(p, (char **)&p, 0); 134 | c2 = strtol(p, (char **)&p, 0); 135 | 136 | b1 = (c1 >> 8) & 0xff; 137 | b2 = (c1) & 0xff; 138 | 139 | /* compress the code */ 140 | b1 = b1 - 0x21; 141 | b2 = b2 - 0x21; 142 | if (b1 > b1_max) 143 | b1_max = b1; 144 | if (b2 > b2_max) 145 | b2_max = b2; 146 | if (b2 > table_b2_max[b1]) 147 | table_b2_max[b1] = b2; 148 | table[b1 * 94 + b2] = c2; 149 | nb++; 150 | } 151 | printf("/* max row = %d. The following rows are excluded:", b1_max); 152 | n = 0; 153 | for(i=0;i<=b1_max;i++) { 154 | if (table_b2_max[i] == 0) { 155 | printf(" %d", i); 156 | } else { 157 | n++; 158 | } 159 | } 160 | printf(", density=%d%% */\n", nb * 100 / (n * (b2_max + 1))); 161 | 162 | printf("const unsigned short table_%s[%d] = {\n", 163 | name, n * (b2_max + 1)); 164 | n = 0; 165 | for(i=0;i<=b1_max;i++) { 166 | if (table_b2_max[i] != 0) { 167 | for(j=0;j<=b2_max;j++) { 168 | printf("0x%04x, ", table[i * 94 + j]); 169 | if ((n++ & 7) == 7) 170 | printf("\n"); 171 | } 172 | } 173 | } 174 | if ((n & 7) != 0) 175 | printf("\n"); 176 | printf("};\n\n"); 177 | } 178 | 179 | int main(int argc, char **argv) 180 | { 181 | int i; 182 | const char *filename, *p; 183 | char *q; 184 | char name[256]; 185 | FILE *f; 186 | 187 | printf("#include \"qe.h\"\n\n"); 188 | 189 | for(i=1;iascent */ 45 | int font_descent; /* maximum font->descent */ 46 | int width; /* sum of glyph widths */ 47 | } QECharMetrics; 48 | 49 | typedef enum QEBitmapFormat { 50 | QEBITMAP_FORMAT_RGB565 = 0, 51 | QEBITMAP_FORMAT_RGB555, 52 | QEBITMAP_FORMAT_RGB24, 53 | QEBITMAP_FORMAT_RGBA32, 54 | QEBITMAP_FORMAT_YUV420P, 55 | } QEBitmapFormat; 56 | 57 | #define QEBITMAP_FLAG_VIDEO 0x0001 /* bitmap used to display video */ 58 | 59 | /* opaque bitmap structure */ 60 | typedef struct QEBitmap { 61 | int width; 62 | int height; 63 | QEBitmapFormat format; 64 | int flags; 65 | void *priv_data; /* driver data */ 66 | } QEBitmap; 67 | 68 | /* draw options */ 69 | #define QEBITMAP_DRAW_HWZOOM 0x0001 70 | 71 | /* user visible picture data (to modify content) */ 72 | typedef struct QEPicture { 73 | int width; 74 | int height; 75 | QEBitmapFormat format; 76 | unsigned char *data[4]; 77 | int linesize[4]; 78 | } QEPicture; 79 | 80 | struct QEditScreen; 81 | typedef struct QEditScreen QEditScreen; 82 | 83 | typedef struct QEDisplay { 84 | const char *name; 85 | int (*dpy_probe)(void); 86 | int (*dpy_init)(QEditScreen *s, int w, int h); 87 | void (*dpy_close)(QEditScreen *s); 88 | void (*dpy_cursor_at)(QEditScreen *s, int x1, int y1, int w, int h); 89 | void (*dpy_flush)(QEditScreen *s); 90 | int (*dpy_is_user_input_pending)(QEditScreen *s); 91 | void (*dpy_fill_rectangle)(QEditScreen *s, 92 | int x, int y, int w, int h, QEColor color); 93 | QEFont *(*dpy_open_font)(QEditScreen *s, int style, int size); 94 | void (*dpy_close_font)(QEditScreen *s, QEFont *font); 95 | void (*dpy_text_metrics)(QEditScreen *s, QEFont *font, 96 | QECharMetrics *metrics, 97 | const unsigned int *str, int len); 98 | void (*dpy_draw_text)(QEditScreen *s, QEFont *font, 99 | int x, int y, const unsigned int *str, int len, 100 | QEColor color); 101 | void (*dpy_set_clip)(QEditScreen *s, 102 | int x, int y, int w, int h); 103 | void (*dpy_selection_activate)(QEditScreen *s); 104 | void (*dpy_selection_request)(QEditScreen *s); 105 | /* bitmap support */ 106 | int (*dpy_bmp_alloc)(QEditScreen *s, QEBitmap *b); 107 | void (*dpy_bmp_free)(QEditScreen *s, QEBitmap *b); 108 | void (*dpy_bmp_draw)(QEditScreen *s, QEBitmap *b, 109 | int dst_x, int dst_y, int dst_w, int dst_h, 110 | int offset_x, int offset_y, int flags); 111 | void (*dpy_bmp_lock)(QEditScreen *s, QEBitmap *bitmap, QEPicture *pict, 112 | int x1, int y1, int w1, int h1); 113 | void (*dpy_bmp_unlock)(QEditScreen *s, QEBitmap *b); 114 | /* full screen support */ 115 | void (*dpy_full_screen)(QEditScreen *s, int full_screen); 116 | struct QEDisplay *next; 117 | } QEDisplay; 118 | 119 | struct QEditScreen { 120 | struct QEDisplay dpy; 121 | int width, height; 122 | QECharset *charset; /* the charset of the TTY, XXX: suppress that, 123 | use a system in fonts instead */ 124 | int media; /* media type (see CSS_MEDIA_xxx) */ 125 | int bitmap_format; /* supported bitmap format */ 126 | int video_format; /* supported video format */ 127 | /* clip region handling */ 128 | int clip_x1, clip_y1; 129 | int clip_x2, clip_y2; 130 | void *private; 131 | }; 132 | 133 | static inline void draw_text(QEditScreen *s, QEFont *font, 134 | int x, int y, const unsigned int *str, int len, 135 | QEColor color) 136 | { 137 | s->dpy.dpy_draw_text(s, font, x, y, str, len, color); 138 | } 139 | 140 | static inline QEFont *open_font(QEditScreen *s, 141 | int style, int size) 142 | { 143 | return s->dpy.dpy_open_font(s, style, size); 144 | } 145 | 146 | static inline void close_font(QEditScreen *s, QEFont *font) 147 | { 148 | s->dpy.dpy_close_font(s, font); 149 | } 150 | 151 | static inline void text_metrics(QEditScreen *s, QEFont *font, 152 | QECharMetrics *metrics, 153 | const unsigned int *str, int len) 154 | { 155 | s->dpy.dpy_text_metrics(s, font, metrics, str, len); 156 | } 157 | 158 | /* XXX: only needed for backward compatibility */ 159 | static inline int glyph_width(QEditScreen *s, QEFont *font, int ch) 160 | { 161 | unsigned int buf[1]; 162 | QECharMetrics metrics; 163 | buf[0] = ch; 164 | text_metrics(s, font, &metrics, buf, 1); 165 | return metrics.width; 166 | } 167 | 168 | static inline void dpy_flush(QEditScreen *s) 169 | { 170 | s->dpy.dpy_flush(s); 171 | } 172 | 173 | static inline void dpy_close(QEditScreen *s) 174 | { 175 | s->dpy.dpy_close(s); 176 | } 177 | 178 | void fill_rectangle(QEditScreen *s, 179 | int x1, int y1, int w, int h, QEColor color); 180 | void set_clip_rectangle(QEditScreen *s, CSSRect *r); 181 | void push_clip_rectangle(QEditScreen *s, CSSRect *or, CSSRect *r); 182 | 183 | int qe_register_display(QEDisplay *dpy); 184 | QEDisplay *probe_display(void); 185 | QEFont *select_font(QEditScreen *s, int style, int size); 186 | 187 | void selection_activate(QEditScreen *s); 188 | void selection_request(QEditScreen *s); 189 | 190 | QEBitmap *bmp_alloc(QEditScreen *s, int width, int height, int flags); 191 | void bmp_free(QEditScreen *s, QEBitmap *b); 192 | void bmp_draw(QEditScreen *s, QEBitmap *b, 193 | int dst_x, int dst_y, int dst_w, int dst_h, 194 | int offset_x, int offset_y, int flags); 195 | void bmp_lock(QEditScreen *s, QEBitmap *bitmap, QEPicture *pict, 196 | int x1, int y1, int w1, int h1); 197 | void bmp_unlock(QEditScreen *s, QEBitmap *bitmap); 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /xml.c: -------------------------------------------------------------------------------- 1 | /* 2 | * XML text mode for QEmacs. 3 | * Copyright (c) 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | /* colorization states */ 22 | enum { 23 | XML_TAG = 1, 24 | XML_COMMENT, 25 | XML_TAG_SCRIPT, 26 | XML_TAG_STYLE, 27 | XML_STYLE, 28 | XML_SCRIPT = 0x10, /* special mode for inside a script, ored with c mode */ 29 | }; 30 | 31 | void xml_colorize_line(unsigned int *buf, int len, 32 | int *colorize_state_ptr, int state_only) 33 | { 34 | int c, state; 35 | unsigned int *p, *p_start, *p1; 36 | 37 | state = *colorize_state_ptr; 38 | p = buf; 39 | p_start = p; 40 | 41 | /* if already in a state, go directly in the code parsing it */ 42 | if (state & XML_SCRIPT) 43 | goto parse_script; 44 | switch(state) { 45 | case XML_COMMENT: 46 | goto parse_comment; 47 | case XML_TAG: 48 | case XML_TAG_SCRIPT: 49 | goto parse_tag; 50 | case XML_STYLE: 51 | goto parse_style; 52 | default: 53 | break; 54 | } 55 | 56 | for(;;) { 57 | p_start = p; 58 | c = *p; 59 | if (c == '\n') { 60 | goto the_end; 61 | } else if (c == '<' && state == 0) { 62 | p++; 63 | if (p[0] == '!' && p[1] == '-' && p[2] == '-') { 64 | p += 3; 65 | state = XML_COMMENT; 66 | /* wait until end of comment */ 67 | parse_comment: 68 | while (*p != '\n') { 69 | if (p[0] == '-' && p[1] == '-' && p[2] == '>') { 70 | p += 3; 71 | state = 0; 72 | break; 73 | } else { 74 | p++; 75 | } 76 | } 77 | set_color(p_start, p - p_start, QE_STYLE_COMMENT); 78 | } else { 79 | /* we are in a tag */ 80 | if (ustristart(p, "SCRIPT", (const unsigned int **)&p)) { 81 | state = XML_TAG_SCRIPT; 82 | } else if (ustristart(p, "STYLE", (const unsigned int **)&p)) { 83 | state = XML_TAG_STYLE; 84 | } 85 | parse_tag: 86 | while (*p != '\n') { 87 | if (*p == '>') { 88 | p++; 89 | if (state == XML_TAG_SCRIPT) 90 | state = XML_SCRIPT; 91 | else if (state == XML_TAG_STYLE) 92 | state = XML_STYLE; 93 | else 94 | state = 0; 95 | break; 96 | } else { 97 | p++; 98 | } 99 | } 100 | set_color(p_start, p - p_start, QE_STYLE_TAG); 101 | if (state == XML_SCRIPT) { 102 | /* javascript coloring */ 103 | p_start = p; 104 | parse_script: 105 | for(;;) { 106 | if (*p == '\n') { 107 | state &= ~XML_SCRIPT; 108 | c_colorize_line(p_start, p - p_start, &state, state_only); 109 | state |= XML_SCRIPT; 110 | break; 111 | } else if (ustristart(p, "') 115 | p1++; 116 | /* XXX: need to add '\n' */ 117 | state &= ~XML_SCRIPT; 118 | c_colorize_line(p_start, p - p_start, &state, state_only); 119 | state |= XML_SCRIPT; 120 | set_color(p, p1 - p, QE_STYLE_TAG); 121 | p = p1; 122 | state = 0; 123 | break; 124 | } else { 125 | p++; 126 | } 127 | } 128 | } else if (state == XML_STYLE) { 129 | /* stylesheet coloring */ 130 | p_start = p; 131 | parse_style: 132 | for(;;) { 133 | if (*p == '\n') { 134 | set_color(p_start, p - p_start, QE_STYLE_CSS); 135 | break; 136 | } else if (ustristart(p, "') 140 | p1++; 141 | set_color(p_start, p - p_start, QE_STYLE_CSS); 142 | set_color(p, p1 - p, QE_STYLE_TAG); 143 | p = p1; 144 | state = 0; 145 | break; 146 | } else { 147 | p++; 148 | } 149 | } 150 | } 151 | } 152 | } else { 153 | /* text */ 154 | p++; 155 | } 156 | } 157 | the_end: 158 | *colorize_state_ptr = state; 159 | } 160 | 161 | int xml_mode_probe(ModeProbeData *p1) 162 | { 163 | const char *p; 164 | 165 | p = (const char *)p1->buf; 166 | while (css_is_space(*p)) 167 | p++; 168 | if (*p != '<') 169 | return 0; 170 | p++; 171 | if (*p != '!' && *p != '?' && *p != '/' && 172 | !isalpha(*p)) 173 | return 0; 174 | return 90; /* leave some room for more specific XML parser */ 175 | } 176 | 177 | int xml_mode_init(EditState *s, ModeSavedData *saved_data) 178 | { 179 | int ret; 180 | ret = text_mode_init(s, saved_data); 181 | if (ret) 182 | return ret; 183 | set_colorize_func(s, xml_colorize_line); 184 | return 0; 185 | } 186 | 187 | static ModeDef xml_mode; 188 | 189 | int xml_init(void) 190 | { 191 | /* c mode is almost like the text mode, so we copy and patch it */ 192 | memcpy(&xml_mode, &text_mode, sizeof(ModeDef)); 193 | xml_mode.name = "xml"; 194 | xml_mode.mode_probe = xml_mode_probe; 195 | xml_mode.mode_init = xml_mode_init; 196 | 197 | qe_register_mode(&xml_mode); 198 | 199 | return 0; 200 | } 201 | 202 | qe_module_init(xml_init); 203 | -------------------------------------------------------------------------------- /display.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Display system for QEmacs 3 | * Copyright (c) 2000 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | QEDisplay *first_dpy = NULL; 22 | 23 | void fill_rectangle(QEditScreen *s, 24 | int x1, int y1, int w, int h, QEColor color) 25 | { 26 | int x2, y2; 27 | x2 = x1 + w; 28 | y2 = y1 + h; 29 | 30 | /* quick clip rejection */ 31 | if (x2 <= s->clip_x1 || y2 <= s->clip_y1 || 32 | x1 >= s->clip_x2 || y1 >= s->clip_y2) 33 | return; 34 | /* region update */ 35 | if (x2 > s->clip_x2) 36 | x2 = s->clip_x2; 37 | if (y2 > s->clip_y2) 38 | y2 = s->clip_y2; 39 | if (x1 < s->clip_x1) 40 | x1 = s->clip_x1; 41 | if (y1 < s->clip_y1) 42 | y1 = s->clip_y1; 43 | 44 | /* rejection if zero size */ 45 | if (x1 >= x2 || y1 >= y2) 46 | return; 47 | s->dpy.dpy_fill_rectangle(s, x1, y1, x2 - x1, y2 - y1, color); 48 | } 49 | 50 | /* set the clip rectangle (and does not clip by the previous one) */ 51 | void set_clip_rectangle(QEditScreen *s, CSSRect *r) 52 | { 53 | int x1, y1, x2, y2; 54 | x1 = r->x1; 55 | y1 = r->y1; 56 | x2 = r->x2; 57 | y2 = r->y2; 58 | 59 | if (x2 > s->width) 60 | x2 = s->width; 61 | if (y2 > s->height) 62 | y2 = s->height; 63 | if (x1 < 0) 64 | x1 = 0; 65 | if (y1 < 0) 66 | y1 = 0; 67 | 68 | s->clip_x1 = x1; 69 | s->clip_y1 = y1; 70 | s->clip_x2 = x2; 71 | s->clip_y2 = y2; 72 | 73 | s->dpy.dpy_set_clip(s, x1, y1, x2 - x1, y2 - y1); 74 | } 75 | 76 | void push_clip_rectangle(QEditScreen *s, CSSRect *or, CSSRect *r) 77 | { 78 | int x1, y1, x2, y2; 79 | 80 | /* save old rectangle */ 81 | or->x1 = s->clip_x1; 82 | or->y1 = s->clip_y1; 83 | or->x2 = s->clip_x2; 84 | or->y2 = s->clip_y2; 85 | 86 | /* load and clip new rectangle against the current one */ 87 | x1 = r->x1; 88 | y1 = r->y1; 89 | x2 = r->x2; 90 | y2 = r->y2; 91 | 92 | if (x2 > s->clip_x2) 93 | x2 = s->clip_x2; 94 | if (y2 > s->clip_y2) 95 | y2 = s->clip_y2; 96 | if (x1 < s->clip_x1) 97 | x1 = s->clip_x1; 98 | if (y1 < s->clip_y1) 99 | y1 = s->clip_y1; 100 | 101 | /* set new rectangle */ 102 | s->clip_x1 = x1; 103 | s->clip_y1 = y1; 104 | s->clip_x2 = x2; 105 | s->clip_y2 = y2; 106 | 107 | s->dpy.dpy_set_clip(s, x1, y1, x2 - x1, y2 - y1); 108 | } 109 | 110 | int qe_register_display(QEDisplay *dpy) 111 | { 112 | QEDisplay **p; 113 | p = &first_dpy; 114 | while (*p != NULL) 115 | p = &(*p)->next; 116 | *p = dpy; 117 | dpy->next = NULL; 118 | return 0; 119 | } 120 | 121 | QEDisplay *probe_display(void) 122 | { 123 | QEDisplay *p, *dpy; 124 | int probe_max, probe; 125 | p = first_dpy; 126 | dpy = NULL; 127 | probe_max = 0; 128 | while (p != NULL) { 129 | probe = p->dpy_probe(); 130 | if (probe >= probe_max) { 131 | probe_max = probe; 132 | dpy = p; 133 | } 134 | p = p->next; 135 | } 136 | return dpy; 137 | } 138 | 139 | /* simple font cache */ 140 | 141 | #define FONT_CACHE_SIZE 32 142 | static QEFont *font_cache[FONT_CACHE_SIZE]; 143 | static int font_cache_timestamp = 0; 144 | 145 | QEFont *select_font(QEditScreen *s, int style, int size) 146 | { 147 | QEFont *fc; 148 | int i, min_ts, min_index; 149 | 150 | min_ts = MAXINT; 151 | min_index = 0; 152 | for(i=0;istyle == style && fc->size == size) { 156 | fc->timestamp = font_cache_timestamp; 157 | goto the_end; 158 | } 159 | if (fc->timestamp < min_ts) { 160 | min_ts = fc->timestamp; 161 | min_index = i; 162 | } 163 | } else { 164 | min_ts = 0; 165 | min_index = i; 166 | } 167 | } 168 | /* not found : open new font */ 169 | if (font_cache[min_index]) 170 | close_font(s, font_cache[min_index]); 171 | fc = open_font(s, style, size); 172 | if (!fc) 173 | return NULL; 174 | fc->style = style; 175 | fc->size = size; 176 | fc->timestamp = font_cache_timestamp; 177 | font_cache[min_index] = fc; 178 | the_end: 179 | font_cache_timestamp++; 180 | return fc; 181 | } 182 | 183 | void selection_activate(QEditScreen *s) 184 | { 185 | if (s->dpy.dpy_selection_activate) 186 | s->dpy.dpy_selection_activate(s); 187 | } 188 | 189 | void selection_request(QEditScreen *s) 190 | { 191 | if (s->dpy.dpy_selection_request) 192 | s->dpy.dpy_selection_request(s); 193 | } 194 | 195 | QEBitmap *bmp_alloc(QEditScreen *s, int width, int height, int flags) 196 | { 197 | QEBitmap *b; 198 | 199 | if (!s->dpy.dpy_bmp_alloc) 200 | return NULL; 201 | b = malloc(sizeof(QEBitmap)); 202 | if (!b) 203 | return NULL; 204 | b->width = width; 205 | b->height = height; 206 | b->flags = flags; 207 | if (s->dpy.dpy_bmp_alloc(s, b) < 0) { 208 | free(b); 209 | return NULL; 210 | } 211 | return b; 212 | } 213 | 214 | void bmp_free(QEditScreen *s, QEBitmap *b) 215 | { 216 | s->dpy.dpy_bmp_free(s, b); 217 | free(b); 218 | } 219 | 220 | void bmp_draw(QEditScreen *s, QEBitmap *b, 221 | int dst_x, int dst_y, int dst_w, int dst_h, 222 | int offset_x, int offset_y, int flags) 223 | { 224 | s->dpy.dpy_bmp_draw(s, b, dst_x, dst_y, dst_w, dst_h, 225 | offset_x, offset_y, flags); 226 | } 227 | 228 | /* used to access the bitmap data. Return the necessary pointers to 229 | modify the image in 'pict'. */ 230 | void bmp_lock(QEditScreen *s, QEBitmap *bitmap, QEPicture *pict, 231 | int x1, int y1, int w1, int h1) 232 | { 233 | s->dpy.dpy_bmp_lock(s, bitmap, pict, x1, y1, w1, h1); 234 | } 235 | 236 | void bmp_unlock(QEditScreen *s, QEBitmap *bitmap) 237 | { 238 | s->dpy.dpy_bmp_unlock(s, bitmap); 239 | } 240 | 241 | #if 0 242 | /* bitmap cache */ 243 | typedef struct QECachedBitmap { 244 | QEBitmap *bitmap; 245 | char url[1]; 246 | int refcount; 247 | struct QECachedBitmap *next; 248 | } QECachedBitmap; 249 | 250 | /* dst_w or dst_h can be zero if unspecified */ 251 | /* XXX: add scaling for printing */ 252 | QECachedBitmap *cbmp_open(QEditScreen *s, 253 | const char *url, 254 | int dst_w, int dst_h) 255 | { 256 | } 257 | 258 | /* return the DESTINATION size of the bitmap. return non zero if 259 | unknown size */ 260 | int cbmp_get_size(QECachedBitmap *bitmap, int *w_ptr, int *h_ptr) 261 | { 262 | } 263 | 264 | void cbmp_draw(QEditScreen *s, QECachedBitmap *bitmap, 265 | int dst_x, int dst_y, int dst_w, int dst_h, 266 | int offset_x, int offset_y, int flags) 267 | { 268 | } 269 | 270 | void cbmp_close(QEditScreen *cbmp) 271 | { 272 | } 273 | #endif 274 | -------------------------------------------------------------------------------- /ligtoqe.c: -------------------------------------------------------------------------------- 1 | /* convert ligature files to qe binary internal format */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int unicode_to_utf8(char *buf, unsigned int c) 11 | { 12 | char *q; 13 | 14 | q = buf; 15 | if (c < 0x80) { 16 | *q++ = c; 17 | } else { 18 | if (c < 0x800) { 19 | *q++ = (c >> 6) | 0xc0; 20 | } else { 21 | if (c < 0x10000) { 22 | *q++ = (c >> 12) | 0xe0; 23 | } else { 24 | if (c < 0x00200000) { 25 | *q++ = (c >> 18) | 0xf0; 26 | } else { 27 | if (c < 0x04000000) { 28 | *q++ = (c >> 24) | 0xf8; 29 | } else { 30 | *q++ = (c >> 30) | 0xfc; 31 | *q++ = ((c >> 24) & 0x3f) | 0x80; 32 | } 33 | *q++ = ((c >> 18) & 0x3f) | 0x80; 34 | } 35 | *q++ = ((c >> 12) & 0x3f) | 0x80; 36 | } 37 | *q++ = ((c >> 6) & 0x3f) | 0x80; 38 | } 39 | *q++ = (c & 0x3f) | 0x80; 40 | } 41 | *q = '\0'; 42 | return q - buf; 43 | } 44 | 45 | void put_be16(FILE *outfile, int off) 46 | { 47 | fputc((off >> 8) & 0xff, outfile); 48 | fputc((off) & 0xff, outfile); 49 | } 50 | 51 | #define MAX_LIGS 5000 52 | 53 | typedef struct Ligature { 54 | int buf_in[20], buf_out[20]; 55 | int buf_in_size, buf_out_size; 56 | } Ligature; 57 | 58 | Ligature ligs[MAX_LIGS]; 59 | int nb_ligs; 60 | 61 | int sort_func(const void *a1, const void *b1) 62 | { 63 | const Ligature *a = a1; 64 | const Ligature *b = b1; 65 | int val; 66 | 67 | val = a->buf_in[0] - b->buf_in[0]; 68 | if (val == 0 && 69 | a->buf_in_size >= 2 && b->buf_in_size >= 2) { 70 | val = a->buf_in[1] - b->buf_in[1]; 71 | } 72 | return val; 73 | } 74 | 75 | void help(void) 76 | { 77 | printf("usage: ligtoqe [-u] sourcefile.lig output_ligature_file\n" 78 | "Build a ligature resource file for qemacs\n" 79 | "\n" 80 | "-u : output an UTF8 encode summy on stdout\n"); 81 | exit(1); 82 | } 83 | 84 | int main(int argc, char **argv) 85 | { 86 | FILE *f, *outfile; 87 | char buf[1024], *p; 88 | Ligature *l; 89 | char buf1[128]; 90 | int i, c, to_utf8, j, l1, l2, n; 91 | const char *lig_filename; 92 | const char *lig_res_filename; 93 | int subst1_count, subst2_count, subst_long_count; 94 | 95 | to_utf8 = 0; 96 | for(;;) { 97 | c = getopt(argc, argv, "uh"); 98 | if (c == -1) 99 | break; 100 | switch(c) { 101 | case 'h': 102 | help(); 103 | break; 104 | case 'u': 105 | to_utf8 = 1; 106 | break; 107 | } 108 | } 109 | if (optind + 2 > argc) 110 | help(); 111 | lig_filename = argv[optind++]; 112 | lig_res_filename = argv[optind++]; 113 | 114 | f = fopen(lig_filename, "r"); 115 | if (!f) { 116 | perror(lig_filename); 117 | return 1; 118 | } 119 | for(;;) { 120 | if (fgets(buf, sizeof(buf), f) == NULL) 121 | break; 122 | p = buf + strlen(buf) - 1; 123 | if (p >= buf && *p == '\n') 124 | *p = '\0'; 125 | p = buf; 126 | 127 | while (isspace(*p)) 128 | p++; 129 | 130 | if (*p == '#' || *p == '\0') { 131 | if (to_utf8) { 132 | printf("%s\n", buf); 133 | } 134 | continue; 135 | } 136 | 137 | l = &ligs[nb_ligs++]; 138 | 139 | l->buf_in_size = 0; 140 | for(;;) { 141 | while (isspace(*p)) 142 | p++; 143 | if (*p == '=') 144 | break; 145 | if (*p == '\0') { 146 | fprintf(stderr, "'=' expected\n"); 147 | exit(1); 148 | } 149 | l->buf_in[l->buf_in_size++] = strtoul(p, &p, 0); 150 | } 151 | p++; 152 | 153 | l->buf_out_size = 0; 154 | for(;;) { 155 | while (isspace(*p)) 156 | p++; 157 | /* stop at the first comment */ 158 | if (*p == '\0' || *p == '/') 159 | break; 160 | l->buf_out[l->buf_out_size++] = strtoul(p, &p, 0); 161 | } 162 | 163 | if (l->buf_in_size < 1 || 164 | l->buf_out_size < 1) { 165 | fprintf(stderr, "syntax error: '%s'\n", buf); 166 | exit(1); 167 | } 168 | 169 | /* output UTF8 encoded list */ 170 | if (to_utf8) { 171 | printf("%s // ", buf); 172 | for(i=0;ibuf_in_size;i++) { 173 | unicode_to_utf8(buf1, l->buf_in[i]); 174 | printf("%s ", buf1); 175 | } 176 | printf("="); 177 | for(i=0;ibuf_out_size;i++) { 178 | unicode_to_utf8(buf1, l->buf_out[i]); 179 | printf(" %s", buf1); 180 | } 181 | printf("\n"); 182 | } 183 | } 184 | fclose(f); 185 | 186 | 187 | /* sort everything */ 188 | qsort(ligs, nb_ligs, sizeof(Ligature), sort_func); 189 | 190 | outfile = fopen(lig_res_filename, "w"); 191 | if (!outfile) { 192 | perror(lig_res_filename); 193 | exit(1); 194 | } 195 | 196 | /* header */ 197 | fwrite("liga", 1, 4, outfile); 198 | 199 | /* number of entries */ 200 | put_be16(outfile, 0); 201 | put_be16(outfile, 0); 202 | put_be16(outfile, 0); 203 | 204 | /* output the subst table */ 205 | n = 0; 206 | for(i=0;ibuf_in_size == 1) { 209 | if (l->buf_out_size != 1) { 210 | fprintf(stderr, "substitutions of only one char are handled\n"); 211 | exit(1); 212 | } 213 | put_be16(outfile, l->buf_in[0]); 214 | put_be16(outfile, l->buf_out[0]); 215 | n++; 216 | } 217 | } 218 | subst1_count = n; 219 | 220 | /* output the ligature table (2 chars -> 1 char) */ 221 | j = 0; 222 | l1 = 0; 223 | l2 = 0; 224 | n = 0; 225 | for(i=0;ibuf_in_size >= 2) { 228 | if (l->buf_in_size > 2 || l->buf_out_size > 1) { 229 | if (l1 == l->buf_in[0] && 230 | l2 == l->buf_in[1]) { 231 | } else { 232 | put_be16(outfile, l->buf_in[0]); 233 | put_be16(outfile, l->buf_in[1]); 234 | put_be16(outfile, 0); 235 | l1 = l->buf_in[0]; 236 | l2 = l->buf_in[1]; 237 | n++; 238 | } 239 | } else { 240 | put_be16(outfile, l->buf_in[0]); 241 | put_be16(outfile, l->buf_in[1]); 242 | put_be16(outfile, l->buf_out[0]); 243 | n++; 244 | } 245 | } 246 | } 247 | 248 | subst2_count = n; 249 | 250 | /* output the long ligature table */ 251 | n = 0; 252 | for(i=0;ibuf_in_size > 2 || l->buf_out_size > 1) { 255 | put_be16(outfile, l->buf_in_size); 256 | put_be16(outfile, l->buf_out_size); 257 | for(j=0;jbuf_in_size;j++) 258 | put_be16(outfile, l->buf_in[j]); 259 | for(j=0;jbuf_out_size;j++) 260 | put_be16(outfile, l->buf_out[j]); 261 | n += 2 + l->buf_in_size + l->buf_out_size; 262 | } 263 | } 264 | put_be16(outfile, 0); 265 | n++; 266 | 267 | subst_long_count = n; 268 | 269 | fseek(outfile, 4, SEEK_SET); 270 | put_be16(outfile, subst1_count); 271 | put_be16(outfile, subst2_count); 272 | put_be16(outfile, subst_long_count); 273 | 274 | fclose(outfile); 275 | 276 | return 0; 277 | } 278 | -------------------------------------------------------------------------------- /input.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Input method handling for QEmacs. 3 | * Copyright (c) 2000 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | #ifndef WIN32 21 | #include 22 | #endif 23 | 24 | InputMethod *input_methods; 25 | 26 | static int default_input(int *match_len_ptr, 27 | const u8 *data, const unsigned int *buf, int len) 28 | { 29 | return INPUTMETHOD_NOMATCH; 30 | } 31 | 32 | static int unicode_input(int *match_len_ptr, 33 | const u8 *data, const unsigned int *buf, int len) 34 | { 35 | int i, h, c; 36 | if (buf[0] != 'x') 37 | return INPUTMETHOD_NOMATCH; 38 | 39 | c = 0; 40 | if (len > 5) 41 | len = 5; 42 | for(i=1;inext; 69 | m->next = NULL; 70 | *p = m; 71 | } 72 | 73 | #ifdef CONFIG_ALL_KMAPS 74 | 75 | /* XXX: use an edit buffer to access the kmap !!!! */ 76 | 77 | /* parse the internal compressed input method format */ 78 | int kmap_input(int *match_len_ptr, 79 | const u8 *data, const unsigned int *buf, int len) 80 | { 81 | const u8 *p, *p1; 82 | int c, d, i, l, l1, match_len, match_char, match_count, match_real_len; 83 | int nb_prefixes, last_outputc, match, prefix_len, trailing_space; 84 | 85 | p = data; 86 | nb_prefixes = p[0] & 0x7f; 87 | trailing_space = p[0] & 0x80; 88 | p++; 89 | prefix_len = 0; 90 | if (nb_prefixes > 0) { 91 | p1 = p; 92 | for(i=0;i= 1 && c <= 0x1d) { 119 | /* delta */ 120 | last_outputc += c; 121 | break; 122 | } else if (c == 0x1e) { 123 | /* explicit output */ 124 | last_outputc = (p[0] << 8) | p[1]; 125 | p += 2; 126 | break; 127 | } else if (c == 0x1f) { 128 | /* unicode value */ 129 | c = (p[0] << 8) | p[1]; 130 | p += 2; 131 | } 132 | if (l1 < len && c != buf[l1]) 133 | match = 0; 134 | l1++; 135 | if (d) { 136 | /* delta = 1 */ 137 | last_outputc++; 138 | break; 139 | } 140 | } 141 | if (trailing_space) { 142 | if (l1 < len && ' ' != buf[l1]) 143 | match = 0; 144 | l1++; 145 | } 146 | 147 | if (match) { 148 | l = l1; 149 | if (l > len) 150 | l = len; 151 | if (l == match_len) { 152 | match_count++; 153 | } else if (l > match_len) { 154 | match_len = l; 155 | match_real_len = l1; 156 | match_char = last_outputc; 157 | match_count = 1; 158 | } 159 | } 160 | } 161 | the_end: 162 | if (match_len == 0) { 163 | return INPUTMETHOD_NOMATCH; 164 | } else if (match_count > 1 || match_real_len > len) { 165 | return INPUTMETHOD_MORECHARS; 166 | } else { 167 | *match_len_ptr = match_len; 168 | return match_char; 169 | } 170 | } 171 | 172 | static int input_method_fd; 173 | 174 | void load_input_methods(void) 175 | { 176 | char buf[1024], *q; 177 | long file_size; 178 | int fd, offset; 179 | const unsigned char *file_ptr, *p; 180 | InputMethod *m; 181 | 182 | input_method_fd = -1; 183 | 184 | if (find_resource_file(buf, sizeof(buf), "kmaps") < 0) 185 | return; 186 | 187 | fd = open (buf, O_RDONLY); 188 | if (fd < 0) 189 | return; 190 | file_size = lseek(fd, 0, SEEK_END); 191 | file_ptr = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0); 192 | if (file_ptr == MAP_FAILED) { 193 | fail: 194 | close(fd); 195 | return; 196 | } 197 | 198 | if (memcmp(file_ptr, "kmap", 4) != 0) 199 | goto fail; 200 | 201 | p = file_ptr + 4; 202 | for(;;) { 203 | offset = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 204 | p+= 4; 205 | if (offset == 0) 206 | break; 207 | m = malloc(sizeof(InputMethod)); 208 | if (m) { 209 | m->data = file_ptr + offset; 210 | m->input_match = kmap_input; 211 | q = buf; 212 | while (*p != '\0') { 213 | if ((q - buf) < (sizeof(buf) - 1)) 214 | *q++ = *p; 215 | p++; 216 | } 217 | *q = '\0'; 218 | p++; 219 | m->name =strdup(buf); 220 | register_input_method(m); 221 | } 222 | } 223 | 224 | input_method_fd = fd; 225 | } 226 | 227 | void unload_input_methods(void) 228 | { 229 | if (input_method_fd >= 0) { 230 | close(input_method_fd); 231 | input_method_fd = -1; 232 | } 233 | } 234 | #endif 235 | 236 | void input_completion(StringArray *cs, const char *input) 237 | { 238 | InputMethod *m; 239 | int len; 240 | 241 | len = strlen(input); 242 | for(m = input_methods; m != NULL; m = m->next) { 243 | if (!strncmp(m->name, input, len)) 244 | add_string(cs, m->name); 245 | } 246 | } 247 | 248 | void do_set_input_method(EditState *s, const char *input_str) 249 | { 250 | InputMethod *m; 251 | 252 | m = input_methods; 253 | for(;;) { 254 | if (!m) { 255 | put_status(s, "'%s' not found", input_str); 256 | return; 257 | } 258 | if (!strcmp(input_str, m->name)) 259 | break; 260 | m = m->next; 261 | } 262 | s->input_method = m; 263 | s->selected_input_method = m; 264 | } 265 | 266 | void do_switch_input_method(EditState *s) 267 | { 268 | if (!s->input_method) 269 | s->input_method = s->selected_input_method; 270 | else 271 | s->input_method = NULL; 272 | } 273 | 274 | void init_input_methods(void) 275 | { 276 | register_input_method(&default_input_method); 277 | register_input_method(&unicode_input_method); 278 | register_completion("input", input_completion); 279 | #ifdef CONFIG_ALL_KMAPS 280 | load_input_methods(); 281 | #endif 282 | } 283 | 284 | void close_input_methods(void) 285 | { 286 | #ifdef CONFIG_ALL_KMAPS 287 | unload_input_methods(); 288 | #endif 289 | } 290 | -------------------------------------------------------------------------------- /qeconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * default qemacs configuration 3 | */ 4 | CmdDef basic_commands[] = { 5 | CMD1( KEY_DEFAULT, KEY_NONE, "self-insert-command", do_char, ' ') 6 | CMD0( KEY_CTRL('o'), KEY_NONE, "open-line", do_open_line) 7 | CMD1( KEY_CTRL('p'), KEY_UP, "previous-line", do_up_down, -1 ) 8 | CMD1( KEY_CTRL('n'), KEY_DOWN, "next-line", do_up_down, 1 ) 9 | CMD1( KEY_CTRL('b'), KEY_LEFT, "backward-char", do_left_right, -1 ) 10 | CMD1( KEY_CTRL('f'), KEY_RIGHT, "forward-char", do_left_right, 1 ) 11 | CMD1( KEY_META('b'), KEY_CTRL_LEFT, "backward-word", do_word_right, -1 ) 12 | CMD1( KEY_META('f'), KEY_CTRL_RIGHT, "forward-word", do_word_right, 1 ) 13 | CMD1( KEY_META('v'), KEY_PAGEUP, "scroll-down", do_scroll_up_down, -1 ) 14 | CMD1( KEY_CTRL('v'), KEY_PAGEDOWN, "scroll-up", do_scroll_up_down, 1 ) 15 | CMD0( KEY_HOME, KEY_CTRL('a'), "beginning-of-line", do_bol) 16 | CMD0( KEY_END, KEY_CTRL('e'), "end-of-line", do_eol) 17 | CMD0( KEY_ESC1(2), KEY_NONE, "overwrite-mode", do_insert) 18 | CMD0( KEY_CTRL('d'), KEY_DELETE, "delete-char", do_delete_char) 19 | CMD0( 127, KEY_NONE, "backward-delete-char", do_backspace) 20 | CMD1( KEY_META(KEY_BACKSPACE) , KEY_NONE, 21 | "backward-delete-word", do_delete_word, -1) 22 | CMD1( KEY_META('d') , KEY_NONE, "delete-word", do_delete_word, 1) 23 | CMD1( KEY_CTRL('k'), KEY_NONE, "kill-line", do_kill_region, 2 ) 24 | CMD0( KEY_CTRL('@'), KEY_NONE, "set-mark-command", do_set_mark ) 25 | CMD1( KEY_CTRL('w'), KEY_NONE, "kill-region", do_kill_region, 1 ) 26 | CMD1( KEY_META('w'), KEY_NONE, "copy-region", do_kill_region, 0 ) 27 | CMD0( KEY_META('<'), KEY_CTRL_HOME, "beginning-of-buffer", do_bof ) 28 | CMD0( KEY_META('>'), KEY_CTRL_END, "end-of-buffer", do_eof ) 29 | CMD( KEY_META('x'), KEY_NONE, "execute-extended-command\0s{Command: }[command]|command|i", do_execute_command ) 30 | CMD0( KEY_CTRL('u'), KEY_NONE, "universal-argument", do_universal_argument ) 31 | CMD0( KEY_CTRL('y'), KEY_NONE, "yank", do_yank) 32 | CMD0( KEY_META('y'), KEY_NONE, "yank-pop", do_yank_pop) 33 | CMD0( KEY_CTRL('i'), KEY_NONE, "tabulate", do_tab) 34 | CMD0( KEY_CTRL('q'), KEY_NONE, "quoted-insert", do_quote) 35 | CMD1( KEY_CTRLX(KEY_CTRL('s')), KEY_NONE, "save-buffer", do_save, 0 ) 36 | CMD1( KEY_CTRLX('s'), KEY_NONE, "save-buffer", do_save, 0 ) 37 | CMD1( KEY_CTRLX(KEY_CTRL('w')), KEY_NONE, "write-file", do_save, 1 ) 38 | CMD0( KEY_CTRLX(KEY_CTRL('c')), KEY_NONE, "suspend-emacs", do_quit ) 39 | CMD( KEY_CTRLX(KEY_CTRL('f')), KEY_NONE, "find-file\0s{Find file: }[file]|file|", do_load) 40 | CMD( KEY_CTRLX(KEY_CTRL('v')), KEY_NONE, "find-alternate-file\0s{Find alternate file: }[file]|file|", 41 | do_find_alternate_file) 42 | CMD( KEY_CTRLX('b'), KEY_NONE, 43 | "switch-to-buffer\0s{Switch to buffer: }[buffer]|buffer|", do_switch_to_buffer) 44 | CMD( KEY_CTRLX('k'), KEY_NONE, 45 | "kill-buffer\0s{Kill buffer: }[buffer]|buffer|", do_kill_buffer) 46 | CMD( KEY_CTRLX('i'), KEY_NONE, "insert-file\0s{Insert file: }[file]|file|", 47 | do_insert_file) 48 | CMD0( KEY_CTRL('g'), KEY_NONE, "abort", do_break) 49 | CMD0( KEY_NONE, KEY_NONE, "doctor", do_doctor) 50 | CMD1( KEY_CTRL('s'), KEY_NONE, "isearch-forward", do_isearch, 1 ) 51 | CMD1( KEY_CTRL('r'), KEY_NONE, "isearch-backward", do_isearch, -1 ) 52 | CMD( KEY_META('%'), KEY_NONE, "query-replace\0s{Query replace: }|search|s{With: }|replace|", do_query_replace ) 53 | CMD0( KEY_CTRLX('u'), KEY_CTRL('_'), "undo", do_undo) 54 | CMD0( KEY_RET, KEY_NONE, "newline", do_return) 55 | CMD0( KEY_CTRL('l'), KEY_NONE, "refresh", do_refresh) 56 | CMD( KEY_META('g'), KEY_NONE, "goto-line\0i{Goto line: }", do_goto_line) 57 | CMDi( KEY_NONE, KEY_NONE, "goto-char\0i{Goto char: }", do_goto_char) 58 | CMD( KEY_NONE, KEY_NONE, "global-set-key\0s{Set key globally: }s{command: }[command]|command|", do_global_set_key) 59 | CMD0( KEY_CTRLX(KEY_CTRL('q')), KEY_NONE, "vc-toggle-read-only", 60 | do_toggle_read_only) 61 | CMD0( KEY_META('q'), KEY_NONE, "fill-paragraph", do_fill_paragraph) 62 | CMD0( KEY_META('{'), KEY_NONE, "backward-paragraph", do_backward_paragraph) 63 | CMD0( KEY_META('}'), KEY_NONE, "forward-paragraph", do_forward_paragraph) 64 | CMD0( KEY_CTRLX(KEY_CTRL('x')), KEY_NONE, "exchange-point-and-mark", do_exchange_point_and_mark) 65 | CMD1( KEY_META('l'), KEY_NONE, "downcase-word", do_changecase_word, 0) 66 | CMD1( KEY_META('u'), KEY_NONE, "upcase-word", do_changecase_word, 1) 67 | CMD1( KEY_CTRLX(KEY_CTRL('l')), KEY_NONE, "downcase-region", 68 | do_changecase_region, 0) 69 | CMD1( KEY_CTRLX(KEY_CTRL('u')), KEY_NONE, "upcase-region", 70 | do_changecase_region, 1) 71 | 72 | /* keyboard macros */ 73 | CMD0( KEY_CTRLX('('), KEY_NONE, "start-kbd-macro", do_start_macro) 74 | CMD0( KEY_CTRLX(')'), KEY_NONE, "end-kbd-macro", do_end_macro) 75 | CMD0( KEY_CTRLX('e'), KEY_NONE, "call-last-kbd-macro", do_call_macro) 76 | 77 | /* window handling */ 78 | CMD0( KEY_CTRLX('o'), KEY_NONE, "other-window", do_other_window) 79 | CMD1( KEY_CTRLX('0'), KEY_NONE, "delete-window", do_delete_window, 0) 80 | CMD0( KEY_CTRLX('1'), KEY_NONE, "delete-other-windows", do_delete_other_windows) 81 | CMD1( KEY_CTRLX('2'), KEY_NONE, "split-window-vertically", do_split_window, 0) 82 | CMD1( KEY_CTRLX('3'), KEY_NONE, "split-window-horizontally", do_split_window, 1) 83 | 84 | /* help */ 85 | CMD0( KEY_CTRLH(KEY_CTRL('h')), KEY_F1, "help-for-help", do_help_for_help) 86 | CMD0( KEY_CTRLH('b'), KEY_NONE, "describe-bindings", 87 | do_describe_bindings) 88 | CMD0( KEY_CTRLH('c'), KEY_NONE, "describe-key-briefly", 89 | do_describe_key_briefly) 90 | 91 | /* international */ 92 | CMD( KEY_CTRLXRET('f'), KEY_NONE, "set-buffer-file-coding-system\0s{Charset: }[charset]", 93 | do_set_buffer_file_coding_system) 94 | CMD( KEY_NONE, KEY_NONE, "convert-buffer-file-coding-system\0s{Charset: }[charset]", 95 | do_convert_buffer_file_coding_system) 96 | CMD0( KEY_CTRLXRET('b'), KEY_NONE, "toggle-bidir", do_toggle_bidir) 97 | CMD( KEY_CTRLXRET(KEY_CTRL('\\')), KEY_NONE, 98 | "set-input-method\0s{Input method: }[input]", do_set_input_method) 99 | CMD0( KEY_CTRL('\\'), KEY_NONE, 100 | "switch-input-method", do_switch_input_method) 101 | 102 | /* styles & display */ 103 | CMD( KEY_NONE, KEY_NONE, "set-style\0s{Style: }[style]|style|s{CSS Property Name: }s{CSS Property Value: }", do_set_style) 104 | CMD( KEY_NONE, KEY_NONE, "set-display-size\0i{Width: }i{Height: }", do_set_display_size) 105 | CMD( KEY_NONE, KEY_NONE, "set-system-font\0ss", do_set_system_font) 106 | CMD0( KEY_CTRLX('f'), KEY_NONE, "toggle-full-screen", do_toggle_full_screen) 107 | CMD0( KEY_NONE, KEY_NONE, "toggle-mode-line", do_toggle_mode_line) 108 | 109 | /* non standard mappings */ 110 | CMD0( KEY_CTRLXRET('l'), KEY_NONE, "toggle-line-numbers", do_line_numbers) 111 | CMD0( KEY_CTRLXRET('t'), KEY_NONE, "truncate-lines", do_line_truncate ) 112 | CMD0( KEY_CTRLXRET('w'), KEY_NONE, "word-wrap", do_word_wrap) 113 | 114 | /* tab & indent */ 115 | CMD( KEY_NONE, KEY_NONE, "set-tab-width\0i{Tab width: }", do_set_tab_width) 116 | CMD( KEY_NONE, KEY_NONE, "set-indent-width\0i{Indent width: }", 117 | do_set_indent_width) 118 | CMD( KEY_NONE, KEY_NONE, "set-indent-tabs-mode\0i{Indent tabs mode (0 or 1): }", 119 | do_set_indent_tabs_mode) 120 | CMD_DEF_END, 121 | }; 122 | 123 | CmdDef minibuffer_commands[] = { 124 | CMD1( KEY_RET, KEY_NONE, "minibuffer-exit", do_minibuffer_exit, 0) 125 | CMD1( KEY_CTRL('g'), KEY_NONE, "minibuffer-abort", do_minibuffer_exit, 1) 126 | CMD0( KEY_CTRL('i'), KEY_NONE, "minibuffer-complete", do_completion) 127 | CMD0( ' ', KEY_NONE, "minibuffer-complete-space", do_completion_space) 128 | CMD1( KEY_CTRL('p'), KEY_UP, "previous-history-element", do_history, -1 ) 129 | CMD1( KEY_CTRL('n'), KEY_DOWN, "next-history-element", do_history, 1 ) 130 | CMD_DEF_END, 131 | }; 132 | 133 | CmdDef less_commands[] = { 134 | CMD0( 'q', KEY_CTRL('g'), "less-exit", do_less_quit) 135 | CMD1( '/', KEY_NONE, "less-isearch", do_isearch, 1) 136 | CMD_DEF_END, 137 | }; 138 | 139 | 140 | QEStyleDef qe_styles[QE_STYLE_NB] = { 141 | 142 | #define STYLE_DEF(constant, name, fg_color, bg_color, \ 143 | font_style, font_size) \ 144 | { name, fg_color, bg_color, font_style, font_size }, 145 | 146 | #include "qestyles.h" 147 | 148 | #undef STYLE_DEF 149 | }; 150 | -------------------------------------------------------------------------------- /kmaptoqe.c: -------------------------------------------------------------------------------- 1 | /* convert yudit kmap files to qe binary internal format */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | //#define TEST 10 | 11 | #define NB_MAX 15000 12 | 13 | typedef struct InputEntry { 14 | unsigned char input[10]; 15 | int len; 16 | int output; 17 | } InputEntry; 18 | 19 | InputEntry inputs[NB_MAX]; 20 | int nb_inputs; 21 | char kmap_names[300][128]; 22 | int kmap_offsets[300]; 23 | char name[128]; 24 | int table_start[NB_MAX], nb_starts; 25 | int table_val[NB_MAX]; 26 | int is_chinese_cj, gen_table; 27 | int freq[32]; 28 | FILE *outfile; 29 | unsigned char outbuf[100000], *outbuf_ptr; 30 | 31 | int sort_func(const void *a1, const void *b1) 32 | { 33 | const InputEntry *a = a1; 34 | const InputEntry *b = b1; 35 | int val; 36 | 37 | if (is_chinese_cj) { 38 | val = a->input[0] - b->input[0]; 39 | if (val != 0) 40 | return val; 41 | } 42 | return a->output - b->output; 43 | } 44 | 45 | 46 | int offset, write_data; 47 | 48 | void put_byte(int b) 49 | { 50 | if (write_data) 51 | *outbuf_ptr++ = b; 52 | offset++; 53 | } 54 | 55 | void gen_map(void) 56 | { 57 | int len, c, d, last, delta, k, j; 58 | int last_input0; 59 | 60 | last = 0; 61 | nb_starts = 0; 62 | last_input0 = 0; 63 | offset = 0; 64 | for(k=0;k 30) 87 | delta = 30; 88 | else if (delta < -1) 89 | delta = -1; 90 | freq[delta + 1]++; 91 | #endif 92 | 93 | if (is_chinese_cj) { 94 | assert(input[len-1] == ' '); 95 | len--; 96 | } 97 | 98 | first = 0; 99 | if (gen_table) 100 | first = 1; 101 | 102 | /* c = 0 : end of table 103 | c = 1..0x1d : delta unicode 104 | c = 0x1e : unicode char follows. 105 | c = 0x1f : unicode mapping follows 106 | bit 7 : eof and delta == 1 107 | */ 108 | for(j=first;j= 0x20 && c <= 0x7f) { 114 | put_byte(c | d); 115 | } else { 116 | put_byte(d | 0x1f); 117 | put_byte((c >> 8) & 0xff); 118 | put_byte(c & 0xff); 119 | } 120 | } 121 | /* XXX: potential problem if first == len. We avoid it 122 | by forcing an emission of a unicode char */ 123 | if (first == len) 124 | delta = 0; 125 | if (delta != 1) { 126 | if (delta >= 1 && delta <= 0x1d) { 127 | put_byte(delta); 128 | } else { 129 | put_byte(0x1e); 130 | put_byte((output >> 8) & 0xff); 131 | put_byte(output & 0xff); 132 | } 133 | } 134 | } 135 | put_byte(0); 136 | } 137 | 138 | int main(int argc, char **argv) 139 | { 140 | char *filename; 141 | int i, j, k, col, line_num; 142 | FILE *f; 143 | char line[1024], *p; 144 | unsigned char *q; 145 | int c, size; 146 | int nb_kmaps; 147 | 148 | if (argc < 3) { 149 | printf("usage: kmaptoqe outfile kmaps...\n" 150 | "Convert yudit keyboard maps to qemacs compressed format\n"); 151 | exit(1); 152 | } 153 | outfile = fopen(argv[1], "w"); 154 | if (!outfile) { 155 | perror(argv[1]); 156 | exit(1); 157 | } 158 | outbuf_ptr = outbuf; 159 | 160 | memset(freq, 0, sizeof(freq)); 161 | 162 | nb_kmaps = 0; 163 | for(i=2;i= 256) { 217 | fprintf(stderr, "%s:%d: Invalid char %x %c\n", 218 | filename, line_num, c, c); 219 | } 220 | *q++ = c; 221 | } 222 | inputs[nb_inputs].len = q - inputs[nb_inputs].input; 223 | p++; 224 | inputs[nb_inputs].output = strtoul(p, NULL, 0); 225 | nb_inputs++; 226 | } 227 | 228 | qsort(inputs, nb_inputs, sizeof(InputEntry), sort_func); 229 | 230 | /* first pass to compute offsets */ 231 | write_data = 0; 232 | gen_map(); 233 | 234 | write_data = 1; 235 | 236 | /* write start map */ 237 | put_byte(nb_starts | (is_chinese_cj ? 0x80 : 0)); 238 | if (gen_table) { 239 | for(k=0;k> 16) & 0xff); 243 | put_byte((j >> 8) & 0xff); 244 | put_byte(j & 0xff); 245 | } 246 | } 247 | 248 | gen_map(); 249 | 250 | fclose(f); 251 | } 252 | 253 | #ifdef TEST 254 | for(k=0;k<32;k++) { 255 | fprintf(stderr, "freq[%d] = %d\n", k, freq[k]); 256 | } 257 | #endif 258 | 259 | /* write header */ 260 | size = 4; 261 | for(i=0;i> 24) & 0xff, outfile); 272 | fputc((off >> 16) & 0xff, outfile); 273 | fputc((off >> 8) & 0xff, outfile); 274 | fputc((off >> 0) & 0xff, outfile); 275 | fwrite(kmap_names[i], 1, strlen(kmap_names[i]) + 1, outfile); 276 | } 277 | fputc(0, outfile); 278 | fputc(0, outfile); 279 | fputc(0, outfile); 280 | fputc(0, outfile); 281 | 282 | fwrite(outbuf, 1, outbuf_ptr - outbuf, outfile); 283 | 284 | fclose(outfile); 285 | 286 | return 0; 287 | } 288 | -------------------------------------------------------------------------------- /unix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unix main loop for QEmacs 3 | * Copyright (c) 2002, 2003 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | #include 21 | 22 | /* NOTE: it is strongly inspirated from the 'links' browser API */ 23 | 24 | typedef struct URLHandler { 25 | void *read_opaque; 26 | void (*read_cb)(void *opaque); 27 | void *write_opaque; 28 | void (*write_cb)(void *opaque); 29 | } URLHandler; 30 | 31 | typedef struct PidHandler { 32 | struct PidHandler *next, *prev; 33 | int pid; 34 | void (*cb)(void *opaque, int status); 35 | void *opaque; 36 | } PidHandler; 37 | 38 | typedef struct BottomHalfEntry { 39 | struct BottomHalfEntry *next, *prev; 40 | void (*cb)(void *opaque); 41 | void *opaque; 42 | } BottomHalfEntry; 43 | 44 | struct QETimer { 45 | void *opaque; 46 | void (*cb)(void *opaque); 47 | int timeout; 48 | struct QETimer *next; 49 | }; 50 | 51 | static fd_set url_rfds, url_wfds; 52 | static int url_fdmax; 53 | static URLHandler url_handlers[256]; 54 | int url_exit_request; 55 | static LIST_HEAD(pid_handlers); 56 | static LIST_HEAD(bottom_halves); 57 | static QETimer *first_timer; 58 | 59 | 60 | void set_read_handler(int fd, void (*cb)(void *opaque), void *opaque) 61 | { 62 | url_handlers[fd].read_cb = cb; 63 | url_handlers[fd].read_opaque = opaque; 64 | if (cb) { 65 | if (fd >= url_fdmax) 66 | url_fdmax = fd; 67 | FD_SET(fd, &url_rfds); 68 | } else { 69 | FD_CLR(fd, &url_rfds); 70 | } 71 | } 72 | 73 | void set_write_handler(int fd, void (*cb)(void *opaque), void *opaque) 74 | { 75 | url_handlers[fd].write_cb = cb; 76 | url_handlers[fd].write_opaque = opaque; 77 | if (cb) { 78 | if (fd >= url_fdmax) 79 | url_fdmax = fd; 80 | FD_SET(fd, &url_wfds); 81 | } else { 82 | FD_CLR(fd, &url_wfds); 83 | } 84 | } 85 | 86 | /* register a callback which is called when process 'pid' 87 | terminates. When the callback is set to NULL, it is deleted */ 88 | /* XXX: add consistency check ? */ 89 | int set_pid_handler(int pid, 90 | void (*cb)(void *opaque, int status), void *opaque) 91 | { 92 | PidHandler *p; 93 | 94 | if (cb == NULL) { 95 | list_for_each(p, &pid_handlers) { 96 | if (p->pid == pid) { 97 | list_del(p); 98 | free(p); 99 | break; 100 | } 101 | } 102 | } else { 103 | p = malloc(sizeof(PidHandler)); 104 | if (!p) 105 | return -1; 106 | p->pid = pid; 107 | p->cb = cb; 108 | p->opaque = opaque; 109 | list_add(p, &pid_handlers); 110 | } 111 | return 0; 112 | } 113 | 114 | /* 115 | * add an explicit call back to avoid recursions 116 | */ 117 | void register_bottom_half(void (*cb)(void *opaque), void *opaque) 118 | { 119 | BottomHalfEntry *bh; 120 | 121 | /* Should not fail */ 122 | bh = malloc(sizeof(BottomHalfEntry)); 123 | bh->cb = cb; 124 | bh->opaque = opaque; 125 | list_add(bh, &bottom_halves); 126 | } 127 | 128 | /* 129 | * remove bottom half 130 | */ 131 | void unregister_bottom_half(void (*cb)(void *opaque), void *opaque) 132 | { 133 | BottomHalfEntry *bh, *bh1; 134 | 135 | list_for_each_safe(bh, bh1, &bottom_halves) { 136 | if (bh->cb == cb && bh->opaque == opaque) { 137 | list_del(bh); 138 | free(bh); 139 | } 140 | } 141 | } 142 | 143 | QETimer *qe_add_timer(int delay, void *opaque, void (*cb)(void *opaque)) 144 | { 145 | QETimer *ti; 146 | 147 | ti = malloc(sizeof(QETimer)); 148 | if (!ti) 149 | return NULL; 150 | ti->timeout = get_clock_ms() + delay; 151 | ti->opaque = opaque; 152 | ti->cb = cb; 153 | ti->next = first_timer; 154 | first_timer = ti; 155 | return ti; 156 | } 157 | 158 | void qe_kill_timer(QETimer *ti) 159 | { 160 | QETimer **pt; 161 | pt = &first_timer; 162 | while (*pt != NULL) { 163 | if (*pt == ti) { 164 | *pt = ti->next; 165 | free(ti); 166 | } else { 167 | pt = &(*pt)->next; 168 | } 169 | } 170 | } 171 | 172 | /* execute stacked bottom halves */ 173 | static void __call_bottom_halves(void) 174 | { 175 | BottomHalfEntry *bh; 176 | 177 | while (!list_empty(&bottom_halves)) { 178 | bh = (BottomHalfEntry *)bottom_halves.prev; 179 | list_del(bh); 180 | bh->cb(bh->opaque); 181 | free(bh); 182 | } 183 | } 184 | 185 | static inline void call_bottom_halves(void) 186 | { 187 | if (!list_empty(&bottom_halves)) 188 | __call_bottom_halves(); 189 | } 190 | 191 | /* call timer callbacks and compute maximum next call time to 192 | check_timers() */ 193 | static inline int check_timers(int max_delay) 194 | { 195 | QETimer *ti, **pt; 196 | int timeout, cur_time; 197 | 198 | cur_time = get_clock_ms(); 199 | timeout = cur_time + max_delay; 200 | pt = &first_timer; 201 | for(;;) { 202 | ti = *pt; 203 | if (ti == NULL) 204 | break; 205 | if ((ti->timeout - cur_time) <= 0) { 206 | /* timer expired : suppress it from timer list and call callback */ 207 | *pt = ti->next; 208 | /* warning: a new timer can be added in the callback */ 209 | ti->cb(ti->opaque); 210 | free(ti); 211 | call_bottom_halves(); 212 | } else { 213 | if ((ti->timeout - timeout) < 0) 214 | timeout = ti->timeout; 215 | pt = &ti->next; 216 | } 217 | } 218 | return timeout - cur_time; 219 | } 220 | 221 | void url_block_reset(void) 222 | { 223 | FD_ZERO(&url_rfds); 224 | FD_ZERO(&url_wfds); 225 | url_fdmax = -1; 226 | url_exit_request = 0; 227 | } 228 | 229 | #define MAX_DELAY 500 230 | 231 | /* block until one event */ 232 | void url_block(void) 233 | { 234 | URLHandler *uh; 235 | int ret, i, pid, status, delay; 236 | fd_set rfds, wfds; 237 | PidHandler *ph, *ph1; 238 | struct timeval tv; 239 | 240 | delay = check_timers(MAX_DELAY); 241 | #if 0 242 | { 243 | static int count; 244 | 245 | printf("%5d: delay=%d\n", count++, delay); 246 | } 247 | #endif 248 | tv.tv_sec = delay / 1000; 249 | tv.tv_usec = (delay % 1000) * 1000; 250 | 251 | rfds = url_rfds; 252 | wfds = url_wfds; 253 | ret = select(url_fdmax + 1, &rfds, &wfds, NULL, &tv); 254 | 255 | /* call each handler */ 256 | if (ret > 0) { 257 | uh = url_handlers; 258 | for(i = 0;i <= url_fdmax; i++) { 259 | if (FD_ISSET(i, &rfds)) { 260 | uh->read_cb(uh->read_opaque); 261 | call_bottom_halves(); 262 | } 263 | if (FD_ISSET(i, &wfds)) { 264 | uh->write_cb(uh->write_opaque); 265 | call_bottom_halves(); 266 | } 267 | uh++; 268 | } 269 | } 270 | 271 | /* handle terminated childs */ 272 | for(;;) { 273 | if (list_empty(&pid_handlers)) 274 | break; 275 | pid = waitpid(-1, &status, WNOHANG); 276 | if (pid <= 0) 277 | break; 278 | list_for_each_safe(ph, ph1, &pid_handlers) { 279 | if (ph->pid == pid) { 280 | ph->cb(ph->opaque, status); 281 | call_bottom_halves(); 282 | break; 283 | } 284 | } 285 | } 286 | } 287 | 288 | void url_main_loop(void (*init)(void *opaque), void *opaque) 289 | { 290 | url_block_reset(); 291 | init(opaque); 292 | for(;;) { 293 | if (url_exit_request) 294 | break; 295 | url_block(); 296 | } 297 | } 298 | 299 | /* exit from url loop */ 300 | void url_exit(void) 301 | { 302 | url_exit_request = 1; 303 | } 304 | 305 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include config.mak 2 | 3 | # from configure 4 | #CONFIG_TINY=y 5 | #CONFIG_X11=y 6 | #CONFIG_XFT=y 7 | #CONFIG_WIN32=y 8 | #CONFIG_PNG_OUTPUT=y 9 | #CONFIG_FFMPEG=y 10 | #CONFIG_HTML=y 11 | #CONFIG_DLL=y 12 | #CONFIG_UNICODE_JOIN=y 13 | #CONFIG_ALL_KMAPS=y 14 | 15 | CFLAGS:=-fno-strict-aliasing -Wall -g $(CFLAGS) 16 | # use it for gcc >= 4.7.0 17 | #CFLAGS+=-Wno-unused-but-set-variable 18 | #CFLAGS+=-Werror 19 | ifdef TARGET_GPROF 20 | CFLAGS+= -p 21 | LDFLAGS+= -p 22 | endif 23 | ifdef TARGET_ARCH_X86 24 | #CFLAGS+=-fomit-frame-pointer 25 | ifeq ($(GCC_MAJOR),2) 26 | CFLAGS+=-m386 -malign-functions=0 27 | else 28 | CFLAGS+=-march=i386 -falign-functions=0 29 | endif 30 | endif 31 | DEFINES=-DHAVE_QE_CONFIG_H 32 | 33 | ######################################################## 34 | # do not modify after this 35 | 36 | ifdef CONFIG_WIN32 37 | CONFIG_ALL_KMAPS= 38 | CONFIG_X11= 39 | CONFIG_DLL= 40 | EXE=.exe 41 | endif 42 | 43 | ifdef CONFIG_PNG_OUTPUT 44 | HTMLTOPPM_LIBS+= -lpng 45 | endif 46 | 47 | ifdef CONFIG_DLL 48 | LIBS+=-ldl 49 | # export some qemacs symbols 50 | # XXX: These linker flags cause compile errors on OSX, specifically the -E opt. 51 | # removing does not seem to break compilation in Linux... 52 | # LDFLAGS+=-Wl,-E 53 | endif 54 | LIBS+=-lm 55 | 56 | TARGETS+=qe$(EXE) qe-doc.html 57 | 58 | OBJS=qe.o charset.o buffer.o \ 59 | input.o unicode_join.o display.o util.o hex.o list.o cutils.o 60 | ifndef CONFIG_WIN32 61 | OBJS+= unix.o tty.o 62 | endif 63 | 64 | OBJS+= unihex.o clang.o latex-mode.o xml.o bufed.o 65 | ifndef CONFIG_WIN32 66 | OBJS+= shell.o dired.o 67 | endif 68 | 69 | ifdef CONFIG_WIN32 70 | OBJS+= win32.o 71 | LIBS+= -lgdi32 72 | endif 73 | 74 | # currently not used in qemacs 75 | ifdef CONFIG_CFB 76 | OBJS+= libfbf.o fbfrender.o cfb.o fbffonts.o 77 | endif 78 | 79 | 80 | ifdef CONFIG_OSX 81 | CONFIG_X11= 82 | OBJS+= osx.o 83 | # XXX: no need to include x11 lib on osx anymore I /opt/X11/include 84 | LDFLAGS+=-framework Cocoa 85 | LIBS+=-lobjc 86 | endif 87 | 88 | ifdef CONFIG_X11 89 | OBJS+= x11.o 90 | ifdef CONFIG_XRENDER 91 | LIBS+=-lXrender 92 | endif 93 | ifdef CONFIG_XV 94 | LIBS+=-lXv 95 | endif 96 | LIBS+= -L/usr/X11R6/lib -lXext -lX11 97 | endif 98 | 99 | ifdef CONFIG_HTML 100 | CFLAGS+=-I./libqhtml 101 | DEP_LIBS+=libqhtml/libqhtml.a 102 | LIBS+=-L./libqhtml -lqhtml 103 | OBJS+=html.o docbook.o 104 | ifndef CONFIG_WIN32 105 | TARGETS+=html2png 106 | endif 107 | endif 108 | 109 | ifdef CONFIG_UNICODE_JOIN 110 | OBJS+= charsetmore.o charset_table.o arabic.o indic.o qfribidi.o unihex.o 111 | endif 112 | 113 | ifdef CONFIG_FFMPEG 114 | OBJS+= video.o image.o 115 | DEP_LIBS+=$(FFMPEG_LIBDIR)/libavcodec/libavcodec.a $(FFMPEG_LIBDIR)/libavformat/libavformat.a 116 | LIBS+= -L$(FFMPEG_LIBDIR)/libavcodec -L$(FFMPEG_LIBDIR)/libavformat -lavformat -lavcodec -lz -lpthread 117 | DEFINES+= -I$(FFMPEG_SRCDIR)/libavcodec -I$(FFMPEG_SRCDIR)/libavformat 118 | TARGETS+=ffplay 119 | endif 120 | 121 | # must be the last object 122 | OBJS+= qeend.o 123 | 124 | all: lib $(TARGETS) 125 | 126 | lib: 127 | make -C libqhtml all 128 | 129 | qe_g: $(OBJS) $(DEP_LIBS) 130 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 131 | 132 | qe$(EXE): qe_g 133 | cp $< $@ 134 | $(STRIP) $@ 135 | @ls -l $@ 136 | 137 | ffplay: qe$(EXE) 138 | ln -sf $< $@ 139 | 140 | qe.o: qe.c qe.h qfribidi.h 141 | 142 | charset.o: charset.c qe.h 143 | 144 | buffer.o: buffer.c qe.h 145 | 146 | tty.o: tty.c qe.h 147 | 148 | qfribidi.o: qfribidi.c qfribidi.h 149 | 150 | cfb.o: cfb.c cfb.h fbfrender.h 151 | 152 | fbfrender.o: fbfrender.c fbfrender.h libfbf.h 153 | 154 | html2png.o: html2png.c qe.h 155 | 156 | %.o : %.c 157 | $(CC) $(DEFINES) $(CFLAGS) -o $@ -c $< 158 | 159 | %.o : %.m 160 | $(CC) $(DEFINES) $(CFLAGS) -o $@ -c $< 161 | 162 | clean: 163 | make -C libqhtml clean 164 | rm -f *.o *~ TAGS gmon.out core \ 165 | qe qe_g qe.exe qfribidi kmaptoqe ligtoqe \ 166 | html2png fbftoqe fbffonts.c 167 | 168 | distclean: clean 169 | rm -f config.h config.mak 170 | 171 | install: qe qe.1 kmaps ligatures html2png 172 | install -m 755 qe $(prefix)/bin/qemacs 173 | ln -sf qemacs $(prefix)/bin/qe 174 | ifdef CONFIG_FFMPEG 175 | ln -sf qemacs $(prefix)/bin/ffplay 176 | endif 177 | mkdir -p $(prefix)/share/qe 178 | install kmaps ligatures $(prefix)/share/qe 179 | install qe.1 $(prefix)/man/man1 180 | install -m 755 -s html2png $(prefix)/bin 181 | 182 | TAGS: force 183 | etags *.[ch] 184 | 185 | force: 186 | 187 | # 188 | # tar archive for distribution 189 | # 190 | 191 | FILES=Changelog COPYING README TODO qe.1 config.eg \ 192 | Makefile qe.tcc qemacs.spec \ 193 | hex.c charset.c qe.c qe.h tty.c \ 194 | html.c indic.c unicode_join.c input.c qeconfig.h \ 195 | qeend.c unihex.c arabic.c kmaptoqe.c util.c \ 196 | bufed.c qestyles.h x11.c buffer.c ligtoqe.c \ 197 | qfribidi.c clang.c latex-mode.c xml.c dired.c list.c qfribidi.h html2png.c \ 198 | charsetmore.c charset_table.c cptoqe.c \ 199 | libfbf.c fbfrender.c cfb.c fbftoqe.c libfbf.h fbfrender.h cfb.h \ 200 | display.c osx.h osx.m display.h mpeg.c shell.c \ 201 | docbook.c unifont.lig kmaps xterm-146-dw-patch \ 202 | ligatures qe-doc.texi qe-doc.html \ 203 | tests/HELLO.txt tests/TestPage.txt tests/test-hebrew \ 204 | tests/test-capital-rtl tests/test-capital-rtl.ref \ 205 | tests/testbidi.html \ 206 | plugin-example/Makefile plugin-example/my_plugin.c \ 207 | image.c video.c win32.c configure VERSION \ 208 | cutils.c cutils.h unix.c 209 | 210 | # qhtml library 211 | FILES+=libqhtml/Makefile libqhtml/css.c libqhtml/cssid.h \ 212 | libqhtml/cssparse.c libqhtml/xmlparse.c libqhtml/htmlent.h \ 213 | libqhtml/css.h libqhtml/csstoqe.c \ 214 | libqhtml/docbook.css libqhtml/html.css 215 | 216 | # fonts 217 | FILES+=fonts/fixed10.fbf fonts/fixed12.fbf fonts/fixed13.fbf fonts/fixed14.fbf \ 218 | fonts/helv10.fbf fonts/helv12.fbf fonts/helv14.fbf fonts/helv18.fbf \ 219 | fonts/helv24.fbf fonts/helv8.fbf fonts/times10.fbf fonts/times12.fbf \ 220 | fonts/times14.fbf fonts/times18.fbf fonts/times24.fbf fonts/times8.fbf \ 221 | fonts/unifont.fbf 222 | 223 | FILE=qemacs-$(shell cat VERSION) 224 | 225 | tar: 226 | rm -rf /tmp/$(FILE) 227 | mkdir -p /tmp/$(FILE) 228 | cp -r . /tmp/$(FILE) 229 | ( cd /tmp ; tar zcvf $(FILE).tar.gz $(FILE) ) 230 | rm -rf /tmp/$(FILE) 231 | 232 | # 233 | # Test for bidir algorithm 234 | # 235 | qfribidi: qfribidi.c 236 | $(HOST_CC) $(CFLAGS) -DTEST -o $@ $< 237 | 238 | # 239 | # build ligature table 240 | # 241 | ligtoqe: ligtoqe.c 242 | $(HOST_CC) $(CFLAGS) -o $@ $< 243 | 244 | ifdef BUILD_ALL 245 | ligatures: unifont.lig ligtoqe 246 | ./ligtoqe unifont.lig $@ 247 | endif 248 | 249 | # 250 | # Key maps build (Only useful if you want to build your own maps from yudit maps) 251 | # 252 | KMAPS=Arabic.kmap ArmenianEast.kmap ArmenianWest.kmap Chinese-CJ.kmap \ 253 | Cyrillic.kmap Czech.kmap DE-RU.kmap Danish.kmap Dutch.kmap \ 254 | Esperanto.kmap Ethiopic.kmap French.kmap Georgian.kmap German.kmap \ 255 | Greek.kmap GreekMono.kmap Guarani.kmap Hebrew.kmap HebrewIsraeli.kmap \ 256 | Hungarian.kmap \ 257 | KOI8_R.kmap Kana.kmap Lithuanian.kmap Mnemonic.kmap Polish.kmap \ 258 | Russian.kmap SGML.kmap TeX.kmap Troff.kmap VNtelex.kmap \ 259 | Vietnamese.kmap XKB_iso8859-4.kmap 260 | # Hangul.kmap Hangul2.kmap Hangul3.kmap Unicode2.kmap 261 | KMAPS_DIR=$(prefix)/share/yudit/data 262 | KMAPS:=$(addprefix $(KMAPS_DIR)/, $(KMAPS)) 263 | 264 | kmaptoqe: kmaptoqe.c 265 | $(HOST_CC) $(CFLAGS) -o $@ $< 266 | 267 | ifdef BUILD_ALL 268 | kmaps: kmaptoqe $(KMAPS) 269 | ./kmaptoqe $@ $(KMAPS) 270 | endif 271 | 272 | # 273 | # Code pages (only useful to add your own code pages) 274 | # 275 | CP=8859_2.cp cp1125.cp cp737.cp koi8_r.cp \ 276 | 8859_4.cp cp1250.cp cp850.cp koi8_u.cp viscii.cp\ 277 | 8859_13.cp 8859_5.cp cp1251.cp cp852.cp mac_lat2.cp\ 278 | 8859_15.cp 8859_7.cp cp1257.cp cp866.cp macroman.cp\ 279 | 8859_16.cp 8859_9.cp cp437.cp kamen.cp tcvn5712.cp \ 280 | JIS0208.TXT JIS0212.TXT 281 | CP:=$(addprefix cp/,$(CP)) 282 | 283 | cptoqe: cptoqe.c 284 | $(HOST_CC) $(CFLAGS) -o $@ $< 285 | 286 | ifdef BUILD_ALL 287 | charset_table.c: cptoqe $(CP) 288 | ./cptoqe $(CP) > $@ 289 | endif 290 | 291 | # 292 | # fonts (only needed for html2png) 293 | # 294 | FONTS=fixed10.fbf fixed12.fbf fixed13.fbf fixed14.fbf\ 295 | helv8.fbf helv10.fbf helv12.fbf helv14.fbf helv18.fbf helv24.fbf\ 296 | times8.fbf times10.fbf times12.fbf times14.fbf times18.fbf times24.fbf\ 297 | unifont.fbf 298 | FONTS:=$(addprefix fonts/,$(FONTS)) 299 | 300 | fbftoqe: fbftoqe.c 301 | $(CC) $(CFLAGS) -o $@ $< 302 | 303 | fbffonts.c: fbftoqe $(FONTS) 304 | ./fbftoqe $(FONTS) > $@ 305 | 306 | # 307 | # html2png tool (XML/HTML/CSS2 renderer test tool) 308 | # 309 | OBJS=util.o cutils.o \ 310 | arabic.o indic.o qfribidi.o \ 311 | display.o unicode_join.o charset.o charsetmore.o charset_table.o \ 312 | libfbf.o fbfrender.o cfb.o fbffonts.o 313 | 314 | html2png: html2png.o $(OBJS) libqhtml/libqhtml.a 315 | $(HOST_CC) $(LDFLAGS) -o $@ html2png.o $(OBJS) \ 316 | -L./libqhtml -lqhtml $(HTMLTOPPM_LIBS) 317 | 318 | # autotest target 319 | test: 320 | make -C tests test 321 | 322 | # documentation 323 | qe-doc.html: qe-doc.texi 324 | texi2html -monolithic -number $< 325 | -------------------------------------------------------------------------------- /charsetmore.c: -------------------------------------------------------------------------------- 1 | /* 2 | * More Charsets for QEmacs 3 | * Copyright (c) 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | /********************************************************/ 22 | /* 8 bit charsets */ 23 | 24 | extern QECharset charset_8859_2; 25 | extern QECharset charset_cp1125; 26 | extern QECharset charset_cp737; 27 | extern QECharset charset_koi8_r; 28 | extern QECharset charset_8859_4; 29 | extern QECharset charset_cp1250; 30 | extern QECharset charset_cp850; 31 | extern QECharset charset_koi8_u; 32 | extern QECharset charset_viscii; 33 | extern QECharset charset_8859_13; 34 | extern QECharset charset_8859_5; 35 | extern QECharset charset_cp1251; 36 | extern QECharset charset_cp852; 37 | extern QECharset charset_mac_lat2; 38 | extern QECharset charset_8859_15; 39 | extern QECharset charset_8859_7; 40 | extern QECharset charset_cp1257; 41 | extern QECharset charset_cp866; 42 | extern QECharset charset_macroman; 43 | extern QECharset charset_8859_16; 44 | extern QECharset charset_8859_9; 45 | extern QECharset charset_cp437; 46 | extern QECharset charset_kamen; 47 | extern QECharset charset_tcvn5712; 48 | 49 | void decode_8bit_init(CharsetDecodeState *s) 50 | { 51 | QECharset *charset = s->charset; 52 | unsigned short *table; 53 | int i, n; 54 | 55 | table = s->table; 56 | for(i=0;imin_char;i++) 57 | *table++ = i; 58 | n = charset->max_char - charset->min_char + 1; 59 | for(i=0;iprivate_table[i]; 61 | for(i=charset->max_char + 1;i<256;i++) 62 | *table++ = i; 63 | } 64 | 65 | /* not very fast, but not critical yet */ 66 | unsigned char *encode_8bit(QECharset *charset, unsigned char *q, int c) 67 | { 68 | int i, n; 69 | const unsigned short *table; 70 | 71 | if (c < charset->min_char) { 72 | /* nothing to do */ 73 | } else if (c > charset->max_char && c <= 0xff) { 74 | /* nothing to do */ 75 | } else { 76 | n = charset->max_char - charset->min_char + 1; 77 | table = charset->private_table; 78 | for(i=0;imin_char + i; 85 | } 86 | *q++ = c; 87 | return q; 88 | } 89 | 90 | /********************************************************/ 91 | /* JIS */ 92 | 93 | extern const unsigned short table_jis208[]; 94 | extern const unsigned short table_jis212[]; 95 | 96 | static int jis0208_decode(int b1, int b2) 97 | { 98 | b1 -= 0x21; 99 | b2 -= 0x21; 100 | if (b1 > 83) 101 | return 0; 102 | if (b1 < 8) { 103 | /* do nothing */ 104 | } else if (b1 <= 14) { 105 | return 0; 106 | } else { 107 | b1 -= 7; 108 | } 109 | return table_jis208[b1 * 94 + b2]; 110 | } 111 | 112 | static int jis0212_decode(int b1, int b2) 113 | { 114 | b1 -= 0x21; 115 | b2 -= 0x21; 116 | if (b1 > 76) 117 | return 0; 118 | switch(b1) { 119 | case 0: 120 | case 2: 121 | case 3: 122 | case 4: 123 | case 7: 124 | case 11: 125 | case 12: 126 | case 13: 127 | case 14: 128 | return 0; 129 | case 1: 130 | b1 = 0; 131 | break; 132 | case 5: 133 | case 6: 134 | b1 = b1 - 5 + 1; 135 | break; 136 | case 8: 137 | case 9: 138 | case 10: 139 | b1 = b1 - 8 + 3; 140 | break; 141 | default: 142 | b1 = b1 - 15 + 6; 143 | break; 144 | } 145 | return table_jis212[b1 * 94 + b2]; 146 | } 147 | 148 | static void decode_euc_jp_init(CharsetDecodeState *s) 149 | { 150 | unsigned short *table = s->table; 151 | int i; 152 | for(i=0;i<256;i++) 153 | table[i] = i; 154 | table[0x8e] = ESCAPE_CHAR; 155 | table[0x8f] = ESCAPE_CHAR; 156 | for(i=0xa1;i<=0xfe;i++) 157 | table[i] = ESCAPE_CHAR; 158 | } 159 | 160 | /* XXX: add state */ 161 | static int decode_euc_jp_func(CharsetDecodeState *s, const unsigned char **pp) 162 | { 163 | const unsigned char *p; 164 | int c, c2; 165 | 166 | p = *pp; 167 | c = *p++; 168 | if (c == 0x8e) { 169 | c = *p; 170 | if (c >= 0xa1 && c <= 0xdf) { 171 | c = c - 0xa1 + 0xff61; 172 | p++; 173 | } 174 | } else if (c >= 0xa1) { 175 | c2 = *p; 176 | if (c2 >= 0xa1 && c2 <= 0xfe) { 177 | c2 = jis0208_decode(c & 0x7f, c2 & 0x7f); 178 | if (c2) { 179 | c = c2; 180 | p++; 181 | } 182 | } 183 | } else { 184 | /* 8f case */ 185 | if (p[0] >= 0xa1 && p[0] <= 0xfe && 186 | p[1] >= 0xa1 && p[1] <= 0xfe) { 187 | c2 = jis0212_decode(p[0] & 0x7f, p[1] & 0x7f); 188 | if (c2) { 189 | c = c2; 190 | p += 2; 191 | } 192 | } 193 | } 194 | *pp = p; 195 | return c; 196 | } 197 | 198 | static unsigned char *encode_euc_jp(QECharset *s, unsigned char *q, int c) 199 | { 200 | if (c <= 0x7f) { 201 | *q++ = c; 202 | } else if (c >= 0xff61 && c <= 0xFF9F) { 203 | *q++ = 0x8e; 204 | *q++ = c - 0xff61 + 0xa1; 205 | } else { 206 | /* XXX: do it */ 207 | return NULL; 208 | } 209 | return q; 210 | } 211 | 212 | static QECharset charset_euc_jp = { 213 | "euc-jp", 214 | NULL, 215 | decode_euc_jp_init, 216 | decode_euc_jp_func, 217 | encode_euc_jp, 218 | table_alloc : 1, 219 | }; 220 | 221 | 222 | static void decode_sjis_init(CharsetDecodeState *s) 223 | { 224 | unsigned short *table = s->table; 225 | int i; 226 | 227 | for(i=0;i<256;i++) 228 | table[i] = i; 229 | table['\\'] = 0x00a5; 230 | table[0x80] = '\\'; 231 | for(i=0x81;i<=0x9f;i++) 232 | table[i] = ESCAPE_CHAR; 233 | for(i=0xa1;i<=0xdf;i++) 234 | table[i] = i - 0xa1 + 0xff61; 235 | for(i=0xe0;i<=0xef;i++) 236 | table[i] = ESCAPE_CHAR; 237 | for(i=0xf0;i<=0xfc;i++) 238 | table[i] = ESCAPE_CHAR; 239 | table[0xfd] = 0xa9; 240 | table[0xfe] = 0x2122; 241 | table[0xff] = 0x2026; 242 | } 243 | 244 | /* XXX: add state */ 245 | static int decode_sjis_func(CharsetDecodeState *s, const unsigned char **pp) 246 | { 247 | const unsigned char *p; 248 | int c, c1, c2, adjust, row, col; 249 | 250 | p = *pp; 251 | c = *p++; 252 | if (c >= 0xf0) { 253 | /* user data */ 254 | } else { 255 | c1 = *p; 256 | if ((c1 >= 0x40 && c1 <= 0x7e) || 257 | (c1 >= 0x80 && c1 <= 0xfc)) { 258 | row = c < 0xa0 ? 0x70 : 0xb0; 259 | adjust = (c1 < 0x9f); 260 | col = adjust ? (c1 >= 0x80 ? 32 : 31) : 0x7e; 261 | c2 = jis0208_decode(((c - row) << 1) - adjust, c1 - col); 262 | if (c2) { 263 | c = c2; 264 | p++; 265 | } 266 | } 267 | } 268 | *pp = p; 269 | return c; 270 | } 271 | 272 | static unsigned char *encode_sjis(QECharset *s, unsigned char *q, int c) 273 | { 274 | if (c <= 0x7f) { 275 | *q++ = c; 276 | } else { 277 | /* XXX: do it */ 278 | return NULL; 279 | } 280 | return q; 281 | } 282 | 283 | static QECharset charset_sjis = { 284 | "sjis", 285 | NULL, 286 | decode_sjis_init, 287 | decode_sjis_func, 288 | encode_sjis, 289 | table_alloc : 1, 290 | }; 291 | 292 | int charset_more_init(void) 293 | { 294 | qe_register_charset(&charset_8859_2); 295 | qe_register_charset(&charset_cp1125); 296 | qe_register_charset(&charset_cp737); 297 | qe_register_charset(&charset_koi8_r); 298 | qe_register_charset(&charset_8859_4); 299 | qe_register_charset(&charset_cp1250); 300 | qe_register_charset(&charset_cp850); 301 | qe_register_charset(&charset_koi8_u); 302 | qe_register_charset(&charset_viscii); 303 | qe_register_charset(&charset_8859_13); 304 | qe_register_charset(&charset_8859_5); 305 | qe_register_charset(&charset_cp1251); 306 | qe_register_charset(&charset_cp852); 307 | qe_register_charset(&charset_mac_lat2); 308 | qe_register_charset(&charset_8859_15); 309 | qe_register_charset(&charset_8859_7); 310 | qe_register_charset(&charset_cp1257); 311 | qe_register_charset(&charset_cp866); 312 | qe_register_charset(&charset_macroman); 313 | qe_register_charset(&charset_8859_16); 314 | qe_register_charset(&charset_8859_9); 315 | qe_register_charset(&charset_cp437); 316 | qe_register_charset(&charset_kamen); 317 | qe_register_charset(&charset_tcvn5712); 318 | 319 | qe_register_charset(&charset_sjis); 320 | qe_register_charset(&charset_euc_jp); 321 | return 0; 322 | } 323 | 324 | qe_module_init(charset_more_init); 325 | 326 | 327 | -------------------------------------------------------------------------------- /charset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Basic Charset functions for QEmacs 3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | QECharset *first_charset = NULL; 22 | 23 | static QECharset charset_7bit; 24 | 25 | /* specific tables */ 26 | static unsigned short table_idem[256]; 27 | static unsigned short table_utf8[256]; 28 | 29 | unsigned char utf8_length[256]; 30 | 31 | static const unsigned int min_code[7] = { 32 | 0, 0, 0x80, 0x800, 0x10000, 0x00200000, 0x04000000, 33 | }; 34 | 35 | static const unsigned char first_code_mask[7] = { 36 | 0, 0, 0x1f, 0xf, 0x7, 0x3, 0x1, 37 | }; 38 | 39 | void charset_init(void) 40 | { 41 | int l, i, n; 42 | 43 | memset(utf8_length, 1, 256); 44 | 45 | i = 0xc0; 46 | l = 2; 47 | while (l <= 6) { 48 | n = first_code_mask[l] + 1; 49 | while (n > 0) { 50 | utf8_length[i++] = l; 51 | n--; 52 | } 53 | l++; 54 | } 55 | 56 | for(i=0;i<256;i++) 57 | table_idem[i] = i; 58 | 59 | /* utf8 table */ 60 | for(i=0;i<256;i++) 61 | table_utf8[i] = INVALID_CHAR; 62 | for(i=0;i<0x80;i++) 63 | table_utf8[i] = i; 64 | for(i=0xc0;i<0xfe;i++) 65 | table_utf8[i] = ESCAPE_CHAR; 66 | 67 | qe_register_charset(&charset_8859_1); 68 | qe_register_charset(&charset_utf8); 69 | qe_register_charset(&charset_7bit); 70 | } 71 | 72 | void qe_register_charset(QECharset *charset) 73 | { 74 | QECharset **pp; 75 | pp = &first_charset; 76 | while (*pp != NULL) 77 | pp = &(*pp)->next; 78 | *pp = charset; 79 | } 80 | 81 | /********************************************************/ 82 | /* 8859-1 */ 83 | 84 | static void decode_8859_1_init(CharsetDecodeState *s) 85 | { 86 | s->table = table_idem; 87 | } 88 | 89 | static unsigned char *encode_8859_1(QECharset *charset, 90 | unsigned char *p, int c) 91 | { 92 | if (c <= 0xff) { 93 | *p++ = c; 94 | return p; 95 | } else { 96 | return NULL; 97 | } 98 | } 99 | 100 | static const char *aliases_8859_1[] = { "ISO-8859-1", "iso-ir-100", "latin1", "l1", "819", NULL }; 101 | 102 | QECharset charset_8859_1 = { 103 | "8859-1", 104 | aliases_8859_1, 105 | decode_8859_1_init, 106 | NULL, 107 | encode_8859_1, 108 | }; 109 | 110 | /********************************************************/ 111 | /* 7 bit */ 112 | 113 | static unsigned char *encode_7bit(QECharset *charset, 114 | unsigned char *p, int c) 115 | { 116 | if (c <= 0x7f) { 117 | *p++ = c; 118 | return p; 119 | } else { 120 | return NULL; 121 | } 122 | } 123 | 124 | static const char *aliases_7bit[] = { "us-ascii", "ascii", "7bit", "7-bit", "iso-ir-6", "ANSI_X3.4", "646", NULL }; 125 | 126 | static QECharset charset_7bit = { 127 | "7bit", 128 | aliases_7bit, 129 | decode_8859_1_init, 130 | NULL, 131 | encode_7bit, 132 | }; 133 | 134 | /********************************************************/ 135 | /* UTF8 */ 136 | 137 | /* return the utf8 char and increment 'p' of at least one char. strict 138 | decoding is done (refuse non canonical UTF8) */ 139 | int utf8_decode(const char **pp) 140 | { 141 | unsigned int c, c1; 142 | const unsigned char *p; 143 | int i, l; 144 | 145 | p = (const unsigned char *)*pp; 146 | c = *p++; 147 | if (c < 128) { 148 | /* fast case for ASCII */ 149 | } else { 150 | l = utf8_length[c]; 151 | if (l == 1) 152 | goto fail; /* can only be multi byte code here */ 153 | c = c & first_code_mask[l]; 154 | for(i=1;i= 0xc0) 157 | goto fail; 158 | p++; 159 | c = (c << 6) | (c1 & 0x3f); 160 | } 161 | if (c < min_code[l]) 162 | goto fail; 163 | /* exclude surrogate pairs and special codes */ 164 | if ((c >= 0xd800 && c <= 0xdfff) || 165 | c == 0xfffe || c == 0xffff) 166 | goto fail; 167 | } 168 | *pp = (const char *)p; 169 | return c; 170 | fail: 171 | *pp = (const char *)p; 172 | return INVALID_CHAR; 173 | } 174 | 175 | /* NOTE: the buffer must be at least 6 bytes long. Return the position 176 | of the next char. */ 177 | char *utf8_encode(char *q, int c) 178 | { 179 | if (c < 0x80) { 180 | *q++ = c; 181 | } else { 182 | if (c < 0x800) { 183 | *q++ = (c >> 6) | 0xc0; 184 | } else { 185 | if (c < 0x10000) { 186 | *q++ = (c >> 12) | 0xe0; 187 | } else { 188 | if (c < 0x00200000) { 189 | *q++ = (c >> 18) | 0xf0; 190 | } else { 191 | if (c < 0x04000000) { 192 | *q++ = (c >> 24) | 0xf8; 193 | } else { 194 | *q++ = (c >> 30) | 0xfc; 195 | *q++ = ((c >> 24) & 0x3f) | 0x80; 196 | } 197 | *q++ = ((c >> 18) & 0x3f) | 0x80; 198 | } 199 | *q++ = ((c >> 12) & 0x3f) | 0x80; 200 | } 201 | *q++ = ((c >> 6) & 0x3f) | 0x80; 202 | } 203 | *q++ = (c & 0x3f) | 0x80; 204 | } 205 | return q; 206 | } 207 | 208 | int utf8_to_unicode(unsigned int *dest, int dest_length, 209 | const char *str) 210 | { 211 | const char *p; 212 | unsigned int *uq, *uq_end, c; 213 | 214 | if (dest_length <= 0) 215 | return 0; 216 | 217 | p = str; 218 | uq = dest; 219 | uq_end = dest + dest_length - 1; 220 | for(;;) { 221 | if (uq >= uq_end) 222 | break; 223 | c = utf8_decode(&p); 224 | if (c == '\0') 225 | break; 226 | *uq++ = c; 227 | } 228 | *uq = 0; 229 | return uq - dest; 230 | } 231 | 232 | static void decode_utf8_init(CharsetDecodeState *s) 233 | { 234 | s->table = table_utf8; 235 | } 236 | 237 | static int decode_utf8_func(CharsetDecodeState *s, const unsigned char **pp) 238 | { 239 | return utf8_decode((const char **)pp); 240 | } 241 | 242 | unsigned char *encode_utf8(QECharset *charset, unsigned char *q, int c) 243 | { 244 | return (unsigned char *)utf8_encode((char *)q, c); 245 | } 246 | 247 | static const char *aliases_utf_8[] = { "utf8", NULL }; 248 | 249 | QECharset charset_utf8 = { 250 | "utf-8", 251 | aliases_utf_8, 252 | decode_utf8_init, 253 | decode_utf8_func, 254 | encode_utf8, 255 | }; 256 | 257 | /********************************************************/ 258 | /* generic charset functions */ 259 | 260 | QECharset *find_charset(const char *str) 261 | { 262 | QECharset *p; 263 | const char **pp; 264 | for(p = first_charset; p != NULL; p = p->next) { 265 | if (!strcasecmp(str, p->name)) 266 | return p; 267 | pp = p->aliases; 268 | if (pp) { 269 | for(; *pp != NULL; pp++) { 270 | if (!strcasecmp(str, *pp)) 271 | return p; 272 | } 273 | } 274 | } 275 | return NULL; 276 | } 277 | 278 | void charset_decode_init(CharsetDecodeState *s, QECharset *charset) 279 | { 280 | unsigned short *table; 281 | 282 | s->table = NULL; /* fail safe */ 283 | if (charset->table_alloc) { 284 | table = malloc(256 * sizeof(unsigned short)); 285 | if (!table) { 286 | charset = &charset_8859_1; 287 | } else { 288 | s->table = table; 289 | } 290 | } 291 | s->charset = charset; 292 | s->decode_func = charset->decode_func; 293 | if (charset->decode_init) 294 | charset->decode_init(s); 295 | } 296 | 297 | void charset_decode_close(CharsetDecodeState *s) 298 | { 299 | if (s->charset->table_alloc && 300 | s->charset != &charset_8859_1) 301 | free(s->table); 302 | /* safety */ 303 | memset(s, 0, sizeof(CharsetDecodeState)); 304 | } 305 | 306 | /* detect the charset. Actually only UTF8 is detected */ 307 | QECharset *detect_charset (const unsigned char *buf, int size) 308 | { 309 | int i, l, c, has_utf8; 310 | 311 | has_utf8 = 0; 312 | for(i = 0; i < size;) { 313 | c = buf[i++]; 314 | if ((c >= 0x80 && c < 0xc0) || c >= 0xfe) 315 | goto no_utf8; 316 | l = utf8_length[c]; 317 | while (l > 1) { 318 | has_utf8 = 1; 319 | if (i >= size) 320 | break; 321 | c = buf[i++]; 322 | if (!(c >= 0x80 && c < 0xc0)) { 323 | no_utf8: 324 | has_utf8 = 0; 325 | break; 326 | } 327 | l--; 328 | } 329 | } 330 | if (has_utf8) 331 | return &charset_utf8; 332 | else 333 | return &charset_8859_1; 334 | } 335 | 336 | /* the function uses '?' to indicate that no match could be found in 337 | current charset */ 338 | int unicode_to_charset(unsigned char *buf, unsigned int c, QECharset *charset) 339 | { 340 | unsigned char *q; 341 | 342 | q = charset->encode_func(charset, buf, c); 343 | if (!q) { 344 | q = buf; 345 | *q++ ='?'; 346 | } 347 | *q = '\0'; 348 | return q - buf; 349 | } 350 | -------------------------------------------------------------------------------- /unicode_join.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unicode joining algorithms for QEmacs. 3 | * 4 | * Copyright (c) 2000 Fabrice Bellard. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | #include "qfribidi.h" 21 | #include "qe.h" 22 | 23 | #ifdef CONFIG_UNICODE_JOIN 24 | 25 | /* ligature tables */ 26 | static unsigned short *subst1; 27 | static unsigned short *ligature2; 28 | static unsigned short *ligature_long; 29 | 30 | static int subst1_count = 0; 31 | static int ligature2_count = 0; 32 | 33 | /* XXX: eof ? */ 34 | static int uni_get_be16(FILE *f) 35 | { 36 | int v; 37 | v = fgetc(f) << 8; 38 | v |= fgetc(f); 39 | return v; 40 | } 41 | 42 | static unsigned short *read_array_be16(FILE *f, int n) 43 | { 44 | unsigned short *tab; 45 | int i; 46 | 47 | tab = malloc(n * sizeof(unsigned short)); 48 | if (!tab) 49 | return NULL; 50 | for(i=0;i> 1; 104 | v1 = ligature2[3 * m]; 105 | v2 = ligature2[3 * m + 1]; 106 | if (v1 == l1 && v2 == l2) 107 | return ligature2[3 * m + 2]; 108 | else if (v1 > l1 || (v1 == l1 && v2 > l2)) { 109 | b = m - 1; 110 | } else { 111 | a = m + 1; 112 | } 113 | } 114 | return -1; 115 | } 116 | 117 | /* apply all the ligature rules in logical order. Always return a 118 | smaller buffer */ 119 | static int unicode_ligature(unsigned int *buf_out, 120 | unsigned int *pos_L_to_V, 121 | int len) 122 | { 123 | int l, l1, l2, len1, len2, i, j; 124 | unsigned int *q; 125 | const unsigned short *lig; 126 | unsigned int buf[len]; 127 | 128 | memcpy(buf, buf_out, len * sizeof(int)); 129 | 130 | q = buf_out; 131 | for(i=0;i= 0x202a && l1 <= 0x202e) { 135 | /* LRE, RLE, PDF, RLO, LRO */ 136 | pos_L_to_V[i] = q - buf_out; 137 | i++; 138 | goto found; 139 | } 140 | /* fast test to eliminate common cases */ 141 | if (i == (len - 1)) 142 | goto nolig; 143 | l2 = buf[i + 1]; 144 | if (l1 <= 0x7f && l2 <= 0x7f) 145 | goto nolig; 146 | l = find_ligature(l1, l2); 147 | if (l < 0) 148 | goto nolig; 149 | if (l > 0) { 150 | /* ligature of length 2 found */ 151 | pos_L_to_V[i] = q - buf_out; 152 | pos_L_to_V[i+1] = q - buf_out; 153 | *q++ = l; 154 | i += 2; 155 | } else { 156 | /* generic case : use ligature_long[] table */ 157 | lig = ligature_long; 158 | for(;;) { 159 | len1 = *lig++; 160 | if (len1 == 0) 161 | break; 162 | len2 = *lig++; 163 | if (i + len1 <= len) { 164 | for(j=0;j= 0x2000) /* fast test for non handled scripts */ 206 | continue; 207 | if (c >= 0x600 && c <= 0x6ff) 208 | mask |= UNICODE_ARABIC; 209 | else if (c >= 0x900 && c <= 0x97f) 210 | mask |= UNICODE_INDIC; 211 | } 212 | return mask; 213 | } 214 | 215 | static void compose_char_to_glyph(unsigned int *ctog, int len, unsigned *ctog1) 216 | { 217 | int i; 218 | for(i=0;i dst_size) 257 | len = dst_size; 258 | memcpy(dst, src, len * sizeof(unsigned int)); 259 | if (char_to_glyph_pos) { 260 | for(i=0;i dst_size) 297 | len = dst_size; 298 | memcpy(dst, buf, len * sizeof(unsigned int)); 299 | 300 | if (char_to_glyph_pos) { 301 | memcpy(char_to_glyph_pos, ctog, src_size * sizeof(unsigned int)); 302 | } 303 | } 304 | return len; 305 | } 306 | 307 | #else /* CONFIG_UNICODE_JOIN */ 308 | 309 | 310 | /* fallback unicode functions */ 311 | 312 | void load_ligatures(void) 313 | { 314 | } 315 | 316 | int unicode_to_glyphs(unsigned int *dst, unsigned int *char_to_glyph_pos, 317 | int dst_size, unsigned int *src, int src_size, int reverse) 318 | { 319 | int len, i; 320 | 321 | len = src_size; 322 | if (len > dst_size) 323 | len = dst_size; 324 | memcpy(dst, src, len * sizeof(unsigned int)); 325 | if (char_to_glyph_pos) { 326 | for(i=0;ich != 0 && c->ch != ch) 211 | c++; 212 | return c; 213 | } 214 | 215 | /* ctog is NOT filled because it is not needed. We put it for homogoneity */ 216 | int arab_join(unsigned int *line, unsigned int *ctog, int len) 217 | { 218 | int a, b, c, i, j, res; 219 | const ArabicChar *aa, *bb, *cc; 220 | 221 | a = 0; 222 | for(i=0;ifinal && bb->medial) { 239 | res = bb->medial; 240 | } else if (cc->final && bb->initial) { 241 | res = bb->initial; 242 | } else if (a && bb->final) { 243 | res = bb->final; 244 | } else if (bb->isolated) { 245 | res = bb->isolated; 246 | } else { 247 | res = b; 248 | } 249 | line[j] = res; 250 | 251 | a = 0; 252 | if (bb->initial && cc->final) 253 | a = cc->final; 254 | } 255 | return len; 256 | } 257 | 258 | -------------------------------------------------------------------------------- /hex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hexadecimal modes for QEmacs. 3 | * Copyright (c) 2000, 2001 Fabrice Bellard. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "qe.h" 20 | 21 | extern ModeDef hex_mode; 22 | 23 | static int to_disp(int c) 24 | { 25 | if (c < ' ' || c >= 127) 26 | c = '.'; 27 | return c; 28 | } 29 | 30 | static int hex_backward_offset(EditState *s, int offset) 31 | { 32 | return align(offset, s->disp_width); 33 | } 34 | 35 | static int hex_display(EditState *s, DisplayState *ds, int offset) 36 | { 37 | int j, len, eof; 38 | int offset1; 39 | unsigned char b; 40 | 41 | display_bol(ds); 42 | 43 | display_printf(ds, -1, -1, "%08x ", offset); 44 | eof = 0; 45 | len = s->b->total_size - offset; 46 | if (len > s->disp_width) 47 | len = s->disp_width; 48 | if (s->mode == &hex_mode) { 49 | for(j=0;jdisp_width;j++) { 50 | display_char(ds, -1, -1, ' '); 51 | offset1 = offset + j; 52 | if (j < len) { 53 | eb_read(s->b, offset + j, &b, 1); 54 | display_printhex(ds, offset1, offset1 + 1, b, 2); 55 | } else { 56 | if (!eof) { 57 | eof = 1; 58 | } else { 59 | offset1 = -2; 60 | } 61 | display_printf(ds, offset1, offset1 + 1, " "); 62 | } 63 | if ((j & 7)== 7) 64 | display_char(ds, -1, -1, ' '); 65 | } 66 | display_char(ds, -1, -1, ' '); 67 | display_char(ds, -1, -1, ' '); 68 | } 69 | eof = 0; 70 | for(j=0;jdisp_width;j++) { 71 | offset1 = offset + j; 72 | if (j < len) { 73 | eb_read(s->b, offset + j, &b, 1); 74 | } else { 75 | b = ' '; 76 | if (!eof) { 77 | eof = 1; 78 | } else { 79 | offset1 = -2; 80 | } 81 | } 82 | display_char(ds, offset1, offset1 + 1, to_disp(b)); 83 | } 84 | offset += len; 85 | display_eol(ds, -1, -1); 86 | 87 | if (len >= s->disp_width) 88 | return offset; 89 | else 90 | return -1; 91 | } 92 | 93 | void do_goto_byte(EditState *s, int offset) 94 | { 95 | if (offset < 0 || offset >= s->b->total_size) 96 | return; 97 | s->offset = offset; 98 | } 99 | 100 | void do_set_width(EditState *s, int w) 101 | { 102 | if (w >= 1) { 103 | s->disp_width = w; 104 | s->offset_top = s->mode->text_backward_offset(s, s->offset_top); 105 | } 106 | } 107 | 108 | void do_incr_width(EditState *s, int incr) 109 | { 110 | int w; 111 | w = s->disp_width + incr; 112 | if (w >= 1) 113 | do_set_width(s, w); 114 | } 115 | 116 | 117 | void do_toggle_hex(EditState *s) 118 | { 119 | s->hex_mode = !s->hex_mode; 120 | } 121 | 122 | /* specific hex commands */ 123 | static CmdDef hex_commands[] = { 124 | CMD1( KEY_NONE, KEY_NONE, "decrease-width", do_incr_width, -1) 125 | CMD1( KEY_NONE, KEY_NONE, "increase-width", do_incr_width, 1) 126 | CMD( KEY_NONE, KEY_NONE, "set-width\0i{Width: }", do_set_width) 127 | CMD( KEY_NONE, KEY_NONE, "goto-byte\0i{Goto byte: }", do_goto_byte) 128 | CMD0( KEY_NONE, KEY_NONE, "toggle-hex", do_toggle_hex) 129 | CMD_DEF_END, 130 | }; 131 | 132 | static int ascii_mode_init(EditState *s, ModeSavedData *saved_data) 133 | { 134 | QEFont *font; 135 | QEStyleDef style; 136 | int num_width; 137 | int ret; 138 | 139 | ret = text_mode_init(s, saved_data); 140 | if (ret) 141 | return ret; 142 | 143 | /* get typical number width */ 144 | get_style(s, &style, s->default_style); 145 | font = select_font(s->screen, style.font_style, style.font_size); 146 | num_width = glyph_width(s->screen, font, '0'); 147 | 148 | s->disp_width = (s->screen->width / num_width) - 10; 149 | s->hex_mode = 0; 150 | s->wrap = WRAP_TRUNCATE; 151 | return 0; 152 | } 153 | 154 | static int hex_mode_init(EditState *s, ModeSavedData *saved_data) 155 | { 156 | int ret; 157 | 158 | ret = text_mode_init(s, saved_data); 159 | if (ret) 160 | return ret; 161 | s->disp_width = 16; 162 | s->hex_mode = 1; 163 | s->unihex_mode = 0; 164 | s->hex_nibble = 0; 165 | s->wrap = WRAP_TRUNCATE; 166 | return 0; 167 | } 168 | 169 | int detect_binary(const unsigned char *buf, int size) 170 | { 171 | int i, c; 172 | 173 | for (i = 0; i < size; i++) { 174 | c = buf[i]; 175 | if (c < 32 && 176 | (c != '\r' && c != '\n' && c != '\t' && c != '\e' && c!= '\b')) 177 | return 1; 178 | } 179 | return 0; 180 | } 181 | 182 | static int hex_mode_probe(ModeProbeData *p) 183 | { 184 | if (detect_binary(p->buf, p->buf_size)) 185 | return 50; 186 | else 187 | return 0; 188 | } 189 | 190 | void hex_move_bol(EditState *s) 191 | { 192 | s->offset = align(s->offset, s->disp_width); 193 | } 194 | 195 | void hex_move_eol(EditState *s) 196 | { 197 | s->offset = align(s->offset, s->disp_width) + s->disp_width - 1; 198 | if (s->offset >= s->b->total_size) 199 | s->offset = s->b->total_size; 200 | } 201 | 202 | void hex_move_left_right(EditState *s, int dir) 203 | { 204 | s->offset += dir; 205 | if (s->offset < 0) 206 | s->offset = 0; 207 | else if (s->offset > s->b->total_size) 208 | s->offset = s->b->total_size; 209 | } 210 | 211 | void hex_move_up_down(EditState *s, int dir) 212 | { 213 | s->offset += dir * s->disp_width; 214 | if (s->offset < 0) 215 | s->offset = 0; 216 | else if (s->offset > s->b->total_size) 217 | s->offset = s->b->total_size; 218 | } 219 | 220 | void hex_write_char(EditState *s, int key) 221 | { 222 | unsigned int cur_ch, ch; 223 | int hsize, shift, cur_len, len, h; 224 | unsigned char buf[10]; 225 | 226 | if (s->hex_mode) { 227 | if (s->unihex_mode) 228 | hsize = 4; 229 | else 230 | hsize = 2; 231 | h = to_hex(key); 232 | if (h < 0) 233 | return; 234 | if (s->insert && s->hex_nibble == 0) { 235 | ch = h << ((hsize - 1) * 4); 236 | if (s->unihex_mode) { 237 | len = unicode_to_charset(buf, ch, s->b->charset); 238 | } else { 239 | len = 1; 240 | buf[0] = ch; 241 | } 242 | eb_insert(s->b, s->offset, buf, len); 243 | } else { 244 | if (s->unihex_mode) { 245 | cur_ch = eb_nextc(s->b, s->offset, &cur_len); 246 | cur_len -= s->offset; 247 | } else { 248 | eb_read(s->b, s->offset, buf, 1); 249 | cur_ch = buf[0]; 250 | cur_len = 1; 251 | } 252 | 253 | shift = (hsize - s->hex_nibble - 1) * 4; 254 | ch = (cur_ch & ~(0xf << shift)) | (h << shift); 255 | 256 | if (s->unihex_mode) { 257 | len = unicode_to_charset(buf, ch, s->b->charset); 258 | } else { 259 | len = 1; 260 | buf[0] = ch; 261 | } 262 | 263 | if (cur_len == len) { 264 | eb_write(s->b, s->offset, buf, len); 265 | } else { 266 | eb_delete(s->b, s->offset, cur_len); 267 | eb_insert(s->b, s->offset, buf, len); 268 | } 269 | } 270 | if (++s->hex_nibble == hsize) { 271 | s->hex_nibble = 0; 272 | if (s->offset < s->b->total_size) 273 | s->offset += len; 274 | } 275 | } else { 276 | text_write_char(s, key); 277 | } 278 | } 279 | 280 | void hex_mode_line(EditState *s, char *buf, int buf_size) 281 | { 282 | char *q; 283 | int percent; 284 | 285 | basic_mode_line(s, buf, buf_size, '-'); 286 | q = buf + strlen(buf); 287 | q += sprintf(q, "0x%x--0x%x", 288 | s->offset, s->b->total_size); 289 | percent = 0; 290 | if (s->b->total_size > 0) 291 | percent = (s->offset * 100) / s->b->total_size; 292 | q += sprintf(q, "--%d%%", percent); 293 | } 294 | 295 | ModeDef ascii_mode = { 296 | "ascii", 297 | instance_size: 0, 298 | mode_probe: NULL, 299 | mode_init: ascii_mode_init, 300 | mode_close: text_mode_close, 301 | text_display: hex_display, 302 | text_backward_offset: hex_backward_offset, 303 | 304 | move_up_down: hex_move_up_down, 305 | move_left_right: hex_move_left_right, 306 | move_bol: hex_move_bol, 307 | move_eol: hex_move_eol, 308 | scroll_up_down: text_scroll_up_down, 309 | write_char: text_write_char, 310 | mouse_goto: text_mouse_goto, 311 | mode_line: hex_mode_line, 312 | }; 313 | 314 | ModeDef hex_mode = { 315 | "hex", 316 | instance_size: 0, 317 | mode_probe: hex_mode_probe, 318 | mode_init: hex_mode_init, 319 | mode_close: text_mode_close, 320 | text_display: hex_display, 321 | text_backward_offset: hex_backward_offset, 322 | 323 | move_up_down: hex_move_up_down, 324 | move_left_right: hex_move_left_right, 325 | move_bol: hex_move_bol, 326 | move_eol: hex_move_eol, 327 | scroll_up_down: text_scroll_up_down, 328 | write_char: hex_write_char, 329 | mouse_goto: text_mouse_goto, 330 | mode_line: hex_mode_line, 331 | }; 332 | 333 | static int hex_init(void) 334 | { 335 | /* first register mode(s) */ 336 | qe_register_mode(&ascii_mode); 337 | qe_register_mode(&hex_mode); 338 | 339 | /* commands and default keys */ 340 | qe_register_cmd_table(hex_commands, NULL); 341 | 342 | /* additionnal mode specific keys */ 343 | qe_register_binding(KEY_CTRL_LEFT, "decrease-width", "ascii|hex"); 344 | qe_register_binding(KEY_CTRL_RIGHT, "increase-width", "ascii|hex"); 345 | qe_register_binding(KEY_TAB, "toggle-hex", "hex"); 346 | qe_register_binding(KEY_SHIFT_TAB, "toggle-hex", "hex"); 347 | 348 | return 0; 349 | } 350 | 351 | qe_module_init(hex_init); 352 | --------------------------------------------------------------------------------