📄 oemacs.w
字号:
combinations that are either useful or harmful.Once upon a time the Caps Lock key might have affected the |event_shiftmask|field of an event, but it has no effect now. The shiftmask is always aneven number, contrary to the implications of \.{<xview/win\_input.h>}.@ The function keys will be translated into a four-character code.First comes control-X; then an asterisk; then a letter, \.{a}--\.{o}for function numbers 1--15, respectively; and then another letter,identifying left, right, top, or bottom. The final letter isordinarily `\.l', `\.r', `\.t', or `\.b', respectively. But it is `\.L', `\.R',`\.T', or `\.B' if a Shift key is down. Furthermore the Control keysubtracts 64 from the ASCII code, so you get `\.,', `\.2', `\.4', or`\."' with Control and no Shift. With both Control and Shift you get\.{\\C-L}, \.{\\C-R}, \.{\\C-T}, \.{\\C-B}. A Meta key adds another 128to the code. Thus, each function key leads to eight possibilities.For example, if F4 is pressed when Control and Shift are down, but notMeta, the four-letter code is \.{\\C-X*d\\C-T}. The user could typethat sequence of four characters and get the same effect.Shifted function keys sometimes have a nice mnemonic significance.For example, key R14, also labeled PgDn, is usually bound to the Emacsoperation `\.{scroll-up}', which moves the window down [sic] by onescreenful; we can then bind Shift-R14 to \.{forward-page}, which advancesdown to the next page boundary. In \.{cweb-mode}, the next page boundaryis the next \.{@@*}, beginning a major part of the program. Similarly,it's convenient to bind B7, the keypad `\.+' key, to \.{forward-paragraph}.Then in \.{cweb-mode}, Shift-B7 goes to the next module (the next\.{@@\ } or \.{@@*}).A Composed character will be preceded by \.{\\C-Q}, the Emacs `quote'character, to distinguish it from a character that was generated with theMeta key down. This also applies to the broken-bar character, whichwill incidentally be preceded by AltGraph, which is B3; you'll probablywant to bind B3 to a no-op if broken bars are important to you.@ This program assumes that several key codes have been rebound fromtheir normal values. Namely, the commands$$\vbox{\halign{\.{#}\hfil\crkeysym R2 = threequarters\crkeysym KP\_Subtract = onehalf\crkeysym KP\_Add = onequarter\crkeysym KP\_Enter = threesuperior\crkeysym KP\_Decimal = twosuperior\crkeysym KP\_0 = onesuperior\cr}}$$should be executed by \.{xmodmap}, preferably in the user's \.{.xinitrc} file.This makes the keys act as $3\over4$, $1\over2$, $1\over4$, $^3$, $^2$, and$^1$, respectively. The corresponding 8-bit codes are respectively190, 189, 188, 179, 178, 185. (By the way, can anybody explain why the ISOLATIN-1 code has $^0$, $^2$, and $^3$ in the positions of meta-0, meta-2,and meta-3, while $^1$ is in the position of meta-9?)@.xmodmap@>We haven't actually bound the keys this way to use them in editing.We did it to provide linguistically unimportant codes that OpenWindowswouldn't mess up; its normal conventions make those valuable keysunusable for editing, except as duplicates for other existing keys.We send \.{turn-numlock-on/off} commands so that \.{emacs} can keep insynch with the keyboard state. Namely, it will rebind the functionkeys B4--B8 to their numeric-keypad equivalents while the Num Lock light is on.On the other hand, our remapping does make the Num Lockfeature useless in other (non-Emacs) applications. If you don'trebind the keys as stated, you lose the functionality of R2 and B4--B8,but \.{oemacs} will still work.The Help key is another special case. We don't want to remap it,because it gives useful help information with other OpenWindowsapplications. If Help is pressed without the shift or control key,the |event_id| is zero and the |event_action| is |ACTION_HELP|.Control-Help is similar, but with |ACTION_TEXT_HELP|. Shift-Help ismore complicated; it invokes `helpopen: starting new Viewer', aftergenerating an event that has |event_action=WIN_VISIBILITY_NOTIFY|. Theprogram below considers the Help key B1 to be characterized by anyevent with |event_id=0| and either |event_action!=0| or|event_shiftmask!=CTRLMASK|.@<Translate a function key into a special escape sequence@>={@+register int bank='b'; /* |'l'|, |'r'|, |'t'|, or |'b'| */ register int n; /* function key serial number, |1<=n<=15| */ if (id>=KEY_LEFT(1)) @<Translate an ordinary function key@>@; else if (id>=256) @<Look for Alt or AltGraph@>@; else if (id>=128) @<Translate a special function key or composed character@>@; else if (id>0 || (event_action(event)==0 && event_shiftmask(event)==CTRLMASK)) goto non_function; else n=1; /* Help key */emit_function_key:@<Emit the code for a function key and |return|@>;non_function:;}@ I'm assuming here that the event id codes occur in the order left, right,top, bottom, and that no higher event codes exist.@<Translate an ordinary function key@>={ if (id<KEY_RIGHT(1)) { /* on the left bank */ bank='l';@+n=id-KEY_LEFT(0); } else if (id<KEY_TOP(1)) { /* on the right bank */ bank='r';@+n=id-KEY_RIGHT(0); } else if (id<KEY_BOTTOM(1)) { bank='t';@+n=id-KEY_TOP(0); } else n=id-KEY_BOTTOM(0); goto emit_function_key;}@ The event codes examined here appear in \.{<xview/win\_event.h>}but not in the XView reference manual.@<Look for Alt or AltGraph@>=if (id==SHIFT_ALT) { n=2;@+goto emit_function_key;} else if (id==SHIFT_ALTG) { n=3;@+goto emit_function_key;} else goto non_function;@ The |ttysw_input| routine sends text to a tty's view window.The second parameter is a string, not necessarily terminated by|'\0'| or anything else; the third parameter is the string length.@<Emit the code for a function key and |return|@>={ if (event_shift_is_down(event)) bank-=32; if (event_ctrl_is_down(event)) bank-=64; if (event_meta_is_down(event)) bank+=128; buf[2]=n+'a'-1; buf[3]=bank; ttysw_input(window,buf,4); return NOTIFY_DONE;}@ @<Global...@>=char buf[]="\030*??\021"; /* |030| and |021| give control-X, control-Q */@ @<Translate a special function key or composed character@>=switch (id) {case 190: bank='r';@+n=2;@+goto emit_function_key;case 189: n=8;@+goto emit_function_key;case 188: n=7;@+goto emit_function_key;case 179: n=6;@+goto emit_function_key;case 178: n=5;@+goto emit_function_key;case 185: n=4;@+goto emit_function_key;default: buf[5]=id; /* composed character or broken-bar */ ttysw_input(window,buf+4,2); return NOTIFY_DONE;}@* The NumLock key.The global variable |num_lock_state| will be 0 if the Num Lock indicatorlight is off, 1 if it is on. Whenever an event occurs, we check to seeif |num_lock_state| should change; if so, we change it and send anappropriate command to \.{emacs}.To read the state of the keyboard LED indicator lights, we need an I/Ocontrol command called the |KIOCGLED| ioctl, described on theman page for \.{kb(4m)}.@<Global...@>=int num_lock_state;char turnon[]="\370turn-numlock-on\r", turnoff[]="\370turn-numlock-off\r";int keyboard; /* file descriptor of \.{/dev/kbd} */@ @<Include...@>=#include <sys/file.h> /* definition of |O_RDWR| for |open| */#include <sundev/kbio.h> /* definition of |KIOCGLED| for |ioctl| */@ @d LED_NUM_LOCK 0x1 /* the official definition is in \.{<server/sunevq.h>}, but that header file includes huge gobs of other stuff */@<Update the Num Lock status@>={@+char leds; /* binary encoding of LED lights */ ioctl(keyboard,KIOCGLED,&leds); if ((leds&LED_NUM_LOCK)!=num_lock_state) { num_lock_state=leds&LED_NUM_LOCK; if (num_lock_state) ttysw_input(window,turnon,17); else ttysw_input(window,turnoff,18); }}@ Any ordinary user can apparently open the keyboard as a file. I wouldhave tried read-only access if read-write had failed; but read-write accessgives a sense of power even though I won't be writing anything.@<Special initialization@>=keyboard=open("/dev/kbd",O_RDWR);if (keyboard<0) { fprintf(stderr,"%s: Can't open /dev/kbd!\n",argv[0]); exit(1);}@* Mouse events.When a mouse button is pressed or released, we send \.{emacs} thecodes control-X and ASCII null, followed by a parenthesized listof four numbers and carriage-return.For example, as I was typing this paragraph, Iclicked the left mouse button on the screen just for fun; \.{emacs}received the characters$$\.{\\030\\0(1 18 28 9999)\\r\\030\\0(129 18 28 141)\\r}$$as a result (according to `\.{view-lossage}'). I would have receivedthe same response if I had typed these characters myself, insteadof clicking the mouse.The first of the four numbers identifies the mouse button itselfas the code number 1, 2, or 4 (for left, middle, right), plus 8 ifa Shift key is down, plus 16 if the Control key is down, plus 32if a Meta key is down, plus 128 if the mouse key is being releasedinstead of pressed.The second number is the row number in the frame, the top row beingconsidered row~0.The third number is the column number in the frame, the left column beingconsidered column~0.The fourth number is the elapsed time between this mouse event and theprevious one, in milliseconds. If the elapsed time was 10 seconds ormore, 9999 is substituted.Macros inside \.{emacs} can use the second and third numbers toposition the cursor. The fourth number can be used to determine if theuser is ``double clicking'' or using ``chords.'' Examples of suchmacros appear in the Emacs source file \.{lisp/sun-mouse.el}.Incidentally, the ASCII null character in mouse sequence makes us happy thatthe string parameter to |ttysw_input| is not null-terminated.@<Translate a mouse event...@>={@+register int button_code,elapsed_time; button_code=(id==MS_LEFT? 1: id==MS_MIDDLE? 2: 4); if (event_shift_is_down(event)) button_code += 8; if (event_ctrl_is_down(event)) button_code += 16; if (event_meta_is_down(event)) button_code += 32; if (event_is_up(event)) button_code += 128; @<Compute the time elapsed since the previous mouse event@>; sprintf(mouse_buf+2,"(%d %d %d %d)\r",button_code,@| event_x(event)/char_width, event_y(event)/char_height,@| elapsed_time); ttysw_input(window,mouse_buf,12+strlen(mouse_buf+12)); /* length is at least 12 */ return NOTIFY_DONE;}@ @<Global...@>=char mouse_buf[24]="\030";@ XView's event structure includes |event_time(event)|, which hastype |struct timeval|; this data type is declared in \.{<sys/time.h>},which is one of the files included automatically as a result ofincluding \.{<xview/xview.h>}.A |timeval| structure consists of two |long| integers, |tv_sec| and |tv_usec|,denoting clock time in seconds and microseconds, respectively.@<Compute the time...@>={@+struct timeval now; /* current time */ long delta_sec, delta_usec; /* difference between current and previous time */ now=event_time(event); delta_sec=now.tv_sec-prev_mouse_time.tv_sec; delta_usec=now.tv_usec-prev_mouse_time.tv_usec; if (delta_usec<0) delta_usec+=1000000,delta_sec--; if (delta_sec>=10) elapsed_time=9999; /* infinity (or close enough) */ else elapsed_time=(delta_sec*1000)+(delta_usec/1000); prev_mouse_time=now;}@ @<Global...@>=struct timeval prev_mouse_time;@* Remaining problems. There's a terribly unfortunate bug in thepresent implementation of XView, causing characters of tty subwindowsto be badly painted at crucial times; the rightmost column of pixelsin a character is often clobbered. If I could figure out how togenerate repaint events for the tty subwindow, I might build a mechanisminto \.{oemacs} that does this after the keyboard has been idle for 10seconds, say. This would blink the screen; maybe I'll get used to that,or maybe I'll prefer to refresh the window manually by binding\.{redraw-display} to the L2 and R1 keys. In any case a lot of screenrefreshing is necessary at the moment, alas.(Note added later: I doubt if I'll get used to blinking, and the presentmethod of manual refresh is tolerable so I won't pursue the 10-secondtimer idea. I have meanwhile noticed a procedure |wmgr_refreshwindow(window)|mentioned in \.{<xview/wmgr.h>}; it will presumably refresh anygiven window.Another bug, much less serious, occurs when the window is resized.If the window gets smaller, \.{emacs} isn't told to correct itsassumptions; so it puts information in strange places or offscreen.(Internally, emacs uses the \.{TIOCGWINSZ} or \.{TIOCSWINSZ} ioctl,described in the man page for \.{termio}.)You can work around this by first making the window very small, thenmaking it large.@* Index.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -