diff options
| author | Aurélien Aptel <aurelien.aptel@gmail.com> | 2009-06-16 02:23:46 +0200 |
|---|---|---|
| committer | Aurélien Aptel <aurelien.aptel@gmail.com> | 2009-06-16 02:23:46 +0200 |
| commit | 8b4bfe31ec1075316dbb2e7d21753771ae3e5590 (patch) | |
| tree | 953d59e5604fd73d51e7de0f60913107fb8d41ea | |
| parent | 5d8aa08ba5a13b20166f21540370b01e239819b1 (diff) | |
| download | st-8b4bfe31ec1075316dbb2e7d21753771ae3e5590.tar.gz st-8b4bfe31ec1075316dbb2e7d21753771ae3e5590.zip | |
made kpress() more flexible, removed st.h, added config.h.
| -rw-r--r-- | st.c | 210 |
1 files changed, 181 insertions, 29 deletions
| @@ -1,5 +1,160 @@ | |||
| 1 | /* See LICENSE for licence details. */ | 1 | /* See LICENSE for licence details. */ |
| 2 | #include "st.h" | 2 | /* See LICENSE for licence details. */ |
| 3 | #define _XOPEN_SOURCE | ||
| 4 | #include <ctype.h> | ||
| 5 | #include <errno.h> | ||
| 6 | #include <fcntl.h> | ||
| 7 | #include <locale.h> | ||
| 8 | #include <stdarg.h> | ||
| 9 | #include <stdio.h> | ||
| 10 | #include <stdlib.h> | ||
| 11 | #include <string.h> | ||
| 12 | #include <signal.h> | ||
| 13 | #include <sys/ioctl.h> | ||
| 14 | #include <sys/select.h> | ||
| 15 | #include <sys/stat.h> | ||
| 16 | #include <sys/types.h> | ||
| 17 | #include <sys/wait.h> | ||
| 18 | #include <unistd.h> | ||
| 19 | #include <X11/Xlib.h> | ||
| 20 | #include <X11/keysym.h> | ||
| 21 | #include <X11/Xutil.h> | ||
| 22 | |||
| 23 | #define TNAME "st" | ||
| 24 | |||
| 25 | /* Arbitrary sizes */ | ||
| 26 | #define ESCSIZ 256 | ||
| 27 | #define ESCARG 16 | ||
| 28 | |||
| 29 | #define SERRNO strerror(errno) | ||
| 30 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
| 31 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) | ||
| 32 | #define LEN(a) (sizeof(a) / sizeof(a[0])) | ||
| 33 | #define DEFAULT(a, b) (a) = (a) ? (a) : (b) | ||
| 34 | #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) | ||
| 35 | #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) | ||
| 36 | |||
| 37 | /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ | ||
| 38 | enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; | ||
| 39 | enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; | ||
| 40 | enum { CRset=1 , CRupdate=2 }; | ||
| 41 | enum { TMwrap=1 , TMinsert=2, TMaltcharset }; | ||
| 42 | enum { SCupdate, SCredraw }; | ||
| 43 | |||
| 44 | typedef int Color; | ||
| 45 | |||
| 46 | typedef struct { | ||
| 47 | KeySym k; | ||
| 48 | char s[ESCSIZ]; | ||
| 49 | } Key; | ||
| 50 | |||
| 51 | typedef struct { | ||
| 52 | char c; /* character code */ | ||
| 53 | char mode; /* attribute flags */ | ||
| 54 | Color fg; /* foreground */ | ||
| 55 | Color bg; /* background */ | ||
| 56 | char state; /* state flag */ | ||
| 57 | } Glyph; | ||
| 58 | |||
| 59 | typedef Glyph* Line; | ||
| 60 | |||
| 61 | typedef struct { | ||
| 62 | Glyph attr; /* current char attributes */ | ||
| 63 | char hidden; | ||
| 64 | int x; | ||
| 65 | int y; | ||
| 66 | } TCursor; | ||
| 67 | |||
| 68 | /* Escape sequence structs */ | ||
| 69 | /* ESC <pre> [[ [<priv>] <arg> [;]] <mode>] */ | ||
| 70 | typedef struct { | ||
| 71 | char buf[ESCSIZ+1]; /* raw string */ | ||
| 72 | int len; /* raw string length */ | ||
| 73 | char pre; | ||
| 74 | char priv; | ||
| 75 | int arg[ESCARG+1]; | ||
| 76 | int narg; /* nb of args */ | ||
| 77 | char mode; | ||
| 78 | } Escseq; | ||
| 79 | |||
| 80 | /* Internal representation of the screen */ | ||
| 81 | typedef struct { | ||
| 82 | int row; /* nb row */ | ||
| 83 | int col; /* nb col */ | ||
| 84 | Line* line; /* screen */ | ||
| 85 | TCursor c; /* cursor */ | ||
| 86 | int top; /* top scroll limit */ | ||
| 87 | int bot; /* bottom scroll limit */ | ||
| 88 | int mode; /* terminal mode */ | ||
| 89 | } Term; | ||
| 90 | |||
| 91 | /* Purely graphic info */ | ||
| 92 | typedef struct { | ||
| 93 | Display* dis; | ||
| 94 | Window win; | ||
| 95 | int scr; | ||
| 96 | int w; /* window width */ | ||
| 97 | int h; /* window height */ | ||
| 98 | int ch; /* char height */ | ||
| 99 | int cw; /* char width */ | ||
| 100 | } XWindow; | ||
| 101 | |||
| 102 | #include "config.h" | ||
| 103 | |||
| 104 | /* Drawing Context */ | ||
| 105 | typedef struct { | ||
| 106 | unsigned long col[LEN(colorname)]; | ||
| 107 | XFontStruct* font; | ||
| 108 | GC gc; | ||
| 109 | } DC; | ||
| 110 | |||
| 111 | void die(const char *errstr, ...); | ||
| 112 | void draw(int); | ||
| 113 | void execsh(void); | ||
| 114 | void sigchld(int); | ||
| 115 | char* kmap(KeySym); | ||
| 116 | void kpress(XKeyEvent *); | ||
| 117 | void resize(XEvent *); | ||
| 118 | void run(void); | ||
| 119 | |||
| 120 | int escaddc(char); | ||
| 121 | int escfinal(char); | ||
| 122 | void escdump(void); | ||
| 123 | void eschandle(void); | ||
| 124 | void escparse(void); | ||
| 125 | void escreset(void); | ||
| 126 | |||
| 127 | void tclearregion(int, int, int, int); | ||
| 128 | void tcpos(int); | ||
| 129 | void tcursor(int); | ||
| 130 | void tdeletechar(int); | ||
| 131 | void tdeleteline(int); | ||
| 132 | void tdump(void); | ||
| 133 | void tinsertblank(int); | ||
| 134 | void tinsertblankline(int); | ||
| 135 | void tmoveto(int, int); | ||
| 136 | void tnew(int, int); | ||
| 137 | void tnewline(void); | ||
| 138 | void tputc(char); | ||
| 139 | void tputs(char*, int); | ||
| 140 | void tresize(int, int); | ||
| 141 | void tscroll(void); | ||
| 142 | void tsetattr(int*, int); | ||
| 143 | void tsetchar(char); | ||
| 144 | void tsetscroll(int, int); | ||
| 145 | |||
| 146 | void ttynew(void); | ||
| 147 | void ttyread(void); | ||
| 148 | void ttyresize(int, int); | ||
| 149 | void ttywrite(char *, size_t); | ||
| 150 | |||
| 151 | unsigned long xgetcol(const char *); | ||
| 152 | void xclear(int, int, int, int); | ||
| 153 | void xcursor(int); | ||
| 154 | void xdrawc(int, int, Glyph); | ||
| 155 | void xinit(void); | ||
| 156 | void xscroll(void); | ||
| 157 | |||
| 3 | 158 | ||
| 4 | /* Globals */ | 159 | /* Globals */ |
| 5 | DC dc; | 160 | DC dc; |
| @@ -725,11 +880,11 @@ xinit(void) { | |||
| 725 | xw.dis = XOpenDisplay(NULL); | 880 | xw.dis = XOpenDisplay(NULL); |
| 726 | xw.scr = XDefaultScreen(xw.dis); | 881 | xw.scr = XDefaultScreen(xw.dis); |
| 727 | if(!xw.dis) | 882 | if(!xw.dis) |
| 728 | die("can not open display"); | 883 | die("Can't open display\n"); |
| 729 | 884 | ||
| 730 | /* font */ | 885 | /* font */ |
| 731 | if(!(dc.font = XLoadQueryFont(xw.dis, FONT))) | 886 | if(!(dc.font = XLoadQueryFont(xw.dis, FONT))) |
| 732 | die("can not find font " FONT); | 887 | die("Can't load font %s\n", FONT); |
| 733 | 888 | ||
| 734 | xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing; | 889 | xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing; |
| 735 | xw.ch = dc.font->ascent + dc.font->descent + LINESPACE; | 890 | xw.ch = dc.font->ascent + dc.font->descent + LINESPACE; |
| @@ -834,6 +989,15 @@ draw(int redraw_all) { | |||
| 834 | xcursor(CSdraw); | 989 | xcursor(CSdraw); |
| 835 | } | 990 | } |
| 836 | 991 | ||
| 992 | char* | ||
| 993 | kmap(KeySym k) { | ||
| 994 | int i; | ||
| 995 | for(i = 0; i < LEN(key); i++) | ||
| 996 | if(key[i].k == k) | ||
| 997 | return (char*)key[i].s; | ||
| 998 | return NULL; | ||
| 999 | } | ||
| 1000 | |||
| 837 | void | 1001 | void |
| 838 | kpress(XKeyEvent *e) { | 1002 | kpress(XKeyEvent *e) { |
| 839 | KeySym ksym; | 1003 | KeySym ksym; |
| @@ -841,39 +1005,28 @@ kpress(XKeyEvent *e) { | |||
| 841 | int len; | 1005 | int len; |
| 842 | int meta; | 1006 | int meta; |
| 843 | int shift; | 1007 | int shift; |
| 1008 | char* skmap; | ||
| 844 | 1009 | ||
| 845 | meta = e->state & Mod1Mask; | 1010 | meta = e->state & Mod1Mask; |
| 846 | shift = e->state & ShiftMask; | 1011 | shift = e->state & ShiftMask; |
| 847 | len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); | 1012 | len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); |
| 848 | if(len > 0) { | 1013 | if(skmap = kmap(ksym)) |
| 1014 | ttywrite(skmap, strlen(skmap)); | ||
| 1015 | else if(len > 0) { | ||
| 849 | buf[sizeof(buf)-1] = '\0'; | 1016 | buf[sizeof(buf)-1] = '\0'; |
| 850 | if(meta && len == 1) | 1017 | if(meta && len == 1) |
| 851 | ttywrite("\033", 1); | 1018 | ttywrite("\033", 1); |
| 852 | ttywrite(buf, len); | 1019 | ttywrite(buf, len); |
| 853 | return; | 1020 | } else |
| 854 | } | 1021 | switch(ksym) { |
| 855 | switch(ksym) { | 1022 | case XK_Insert: |
| 856 | default: | 1023 | if(shift) |
| 857 | fprintf(stderr, "errkey: %d\n", (int)ksym); | 1024 | /* XXX: paste X clipboard */; |
| 858 | break; | 1025 | break; |
| 859 | case XK_Up: | 1026 | default: |
| 860 | case XK_Down: | 1027 | fprintf(stderr, "errkey: %d\n", (int)ksym); |
| 861 | case XK_Left: | 1028 | break; |
| 862 | case XK_Right: | 1029 | } |
| 863 | sprintf(buf, "\033[%c", "DACB"[ksym - XK_Left]); | ||
| 864 | ttywrite(buf, 3); | ||
| 865 | break; | ||
| 866 | case XK_Delete: ttywrite(KEYDELETE, sizeof(KEYDELETE)-1); break; | ||
| 867 | case XK_Home: ttywrite(KEYHOME, sizeof(KEYHOME)-1); break; | ||
| 868 | case XK_End: ttywrite(KEYEND, sizeof(KEYEND) -1); break; | ||
| 869 | case XK_Prior: ttywrite(KEYPREV, sizeof(KEYPREV)-1); break; | ||
| 870 | case XK_Next: ttywrite(KEYNEXT, sizeof(KEYNEXT)-1); break; | ||
| 871 | case XK_Insert: | ||
| 872 | /* XXX: paste X clipboard */ | ||
| 873 | if(shift) | ||
| 874 | ; | ||
| 875 | break; | ||
| 876 | } | ||
| 877 | } | 1030 | } |
| 878 | 1031 | ||
| 879 | void | 1032 | void |
| @@ -891,7 +1044,6 @@ resize(XEvent *e) { | |||
| 891 | } | 1044 | } |
| 892 | } | 1045 | } |
| 893 | 1046 | ||
| 894 | |||
| 895 | void | 1047 | void |
| 896 | run(void) { | 1048 | run(void) { |
| 897 | int ret; | 1049 | int ret; |
