home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / emacs-19.28-src.tgz / tar.out / fsf / emacs / src / amiga_tty.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  426 lines

  1. #include "config.h"
  2. #include "lisp.h"
  3. #include "termchar.h"
  4. #include "frame.h"
  5.  
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <sys/time.h>
  9. #include <internal/files.h>
  10. #include <internal/vars.h>
  11.  
  12. #undef LONGBITS
  13.  
  14. #include <exec/types.h>
  15. #include <dos/dos.h>
  16. #include <proto/exec.h>
  17.  
  18. #include "amiga.h"
  19. #include "termhooks.h"
  20.  
  21. #ifdef USE_PROTOS
  22. #include "protos.h"
  23. #endif
  24.  
  25. static int term_initialised;
  26. ULONG inputsig;
  27.  
  28. /* A few tty system dependent routines unused on the Amiga */
  29.  
  30. setpgrp_of_tty(int pid) {}
  31. init_sigio() {}
  32. reset_sigio() {}
  33. request_sigio() {}
  34. unrequest_sigio() {}
  35.  
  36. /* Return nonzero if safe to use tabs in output.
  37.    At the time this is called, init_sys_modes has not been done yet.  */
  38.  
  39. tabs_safe_p()
  40. {
  41.   if (noninteractive)
  42.     return 1;
  43.  
  44.   return 0;            /* Not safe on Amiga !? */
  45. }
  46.  
  47. /* Get terminal size from system.
  48.    Store number of lines into *heightp and width into *widthp.
  49.    If zero or a negative number is stored, the value is not valid.  */
  50.  
  51. get_frame_size (widthp, heightp)
  52.      int *widthp, *heightp;
  53. {
  54. #ifdef MULTI_FRAME
  55.     CHFIXME selected_frame below ok?
  56. #endif
  57.     if (term_initialised && !inhibit_window_system)
  58.     amiga_get_window_size(selected_frame, widthp, heightp);
  59.     else /* We don't known what size the terminal is */
  60.     {
  61.     *widthp = 0;
  62.     *heightp = 0;
  63.     }
  64. }
  65.  
  66. init_baud_rate ()
  67. {
  68.   if (noninteractive || !term_initialised) baud_rate = 1200;
  69.   else if (!inhibit_window_system) baud_rate = 38400;
  70.   else baud_rate = serial_baud_rate();
  71. }
  72.  
  73. void check_intuition ()
  74. {
  75.     if (noninteractive || inhibit_window_system)
  76.         error ("You aren't using a window.");
  77. }
  78.  
  79. #define TTYBUFSIZE 256        /* Same size as kbd_buffer */
  80. static char ttybuf[TTYBUFSIZE];
  81.  
  82. #define NEW_KBD /* use event queue for sending key strokes to emacs */
  83.  
  84. static int tty_count;
  85. #ifndef NEW_KBD
  86. #define TTYPUT(c) { if (tty_count < TTYBUFSIZE) ttybuf[tty_count++] = c; }
  87. #else
  88. #define TTYPUT(c) \
  89. {\
  90.  event.kind = ascii_keystroke; \
  91.  event.code = c; \
  92.  event.modifiers = 0; \
  93.  event.frame_or_window = selected_frame; \
  94.  gettimeofday (&tv, NULL); \
  95.  event.timestamp = tv.tv_usec; \
  96.  kbd_buffer_store_event (&event); \
  97.  set_mouse_event_pending(); /* wakeup emacs */ \
  98. }
  99. #define FTTYPUT(c, qual) \
  100. {\
  101.  event.kind = non_ascii_keystroke; \
  102.  event.code = c; \
  103.  event.modifiers = qual; \
  104.  event.frame_or_window = selected_frame; \
  105.  gettimeofday (&tv, NULL); \
  106.  event.timestamp = tv.tv_usec; \
  107.  kbd_buffer_store_event (&event); \
  108.  set_mouse_event_pending(); /* wakeup emacs */ \
  109. }
  110. #endif
  111.  
  112. static int interrupt_char;
  113.  
  114. /*
  115.  * CHFIXME: will the event scheme break serial support? Add mode dependant code?
  116.  */
  117.  
  118. void enque(unsigned int c, int metaOrQual, int fkey)
  119.     
  120. /* place input keys in keyboard buffer
  121.  
  122. was:
  123.    If high bit is set, precede character with ^Q (hack).
  124.    If meta is true, set high bit.
  125.    If both the high bit & meta are true, we have a problem. Ignore it.
  126.    If c == AMIGASEQ (256) enqueue the amiga sequence introducer (C-x C-^)
  127. now:
  128.    If meta is true, precede key with ESC if key isn\'t ESC.
  129.    Pass high bit as-is.
  130.    If c == AMIGASEQ (256) enqueue the amiga sequence introducer (C-x C-^)
  131.    if fkey is true meta contains full (emacs) qualifier mask and
  132.    c is a non_ascii_event
  133. */
  134. {
  135. #ifdef NEW_KBD
  136.   struct input_event event;
  137.   struct timeval tv;
  138. #endif
  139.  
  140.   if(fkey)
  141.   {
  142.       FTTYPUT(c, metaOrQual);
  143.   }
  144.   /* Hack CSI to be AMIGASEQ (to allow defining function keys, etc) */
  145.   else if (c == 0233 || c == AMIGASEQ)
  146.     {
  147.       TTYPUT('x' & 037);
  148.       TTYPUT('^' & 037);
  149.     }
  150.   else
  151. #if 0 /* test ordinary 8 bit */
  152.       if (c >= 0200)    /* Special character, precede with ^Q */
  153.     {
  154.       TTYPUT('q' & 037);
  155.       TTYPUT(c);
  156.     }
  157.   else
  158. #endif
  159.     {
  160. #if 0
  161.       if (meta) c |= 0200;
  162. #else
  163.       if(metaOrQual && c != 0x1B) TTYPUT(0x1B); /* ESC */
  164. #endif
  165.       if (c == interrupt_char) Signal((struct Task *)_us, SIGBREAKF_CTRL_C);
  166.       else TTYPUT(c);
  167.     }
  168. }
  169.  
  170. int get_ttycount(void)
  171. {
  172.   return tty_count;
  173. }
  174.  
  175. init_sys_modes ()
  176. {
  177.   extern int quit_char;
  178.  
  179.   if (noninteractive)
  180.     return;
  181.  
  182.   if (inhibit_window_system) clear_frame();
  183.  
  184.   interrupt_char = quit_char;
  185.   if (!inhibit_window_system) setup_intchar(interrupt_char);
  186. }
  187.  
  188. reset_sys_modes ()
  189. {
  190.   if (noninteractive)
  191.     {
  192.       fflush (stdout);
  193.       return;
  194.     }
  195.  
  196.   cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
  197.   clear_end_of_line (FRAME_WIDTH (selected_frame));
  198.   /* clear_end_of_line may move the cursor */
  199.   cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
  200. }
  201.  
  202. void amiga_consume_input(void)
  203. {
  204.   extern int this_command_key_count;
  205.   int force = this_command_key_count == 0;
  206.   /* If force is TRUE & some non-keyboard (eg mouse events) input is pending,
  207.      insert the appropriate magic sequence in the input stream */
  208.  
  209.   if (term_initialised)
  210.     {
  211. #ifdef MULTI_FRAME
  212.     CHFIXME check
  213. #endif
  214.       if (!inhibit_window_system) check_window(selected_frame, force);
  215.       else check_serial(force);
  216.       check_arexx(force, TRUE);
  217.     }
  218. }
  219.  
  220. discard_tty_input ()
  221. {
  222.   if (noninteractive)
  223.     return;
  224.  
  225.   amiga_consume_input();
  226.   tty_count = 0;
  227.   chkabort();
  228. }
  229.  
  230. /* Code for the fd describing the emacs input (terminal or window) */
  231.  
  232. static ULONG __regargs ttyin_select_start(void *userinfo, int rd, int wr)
  233. {
  234.   if (!inhibit_window_system) force_window(selected_frame);
  235.  
  236.   return (tty_count || mouse_event_pending()) ? -1 : inputsig;
  237. }
  238.  
  239. static void __regargs ttyin_select_poll(void *userinfo, int *rd, int *wr)
  240. {
  241.   amiga_consume_input();
  242.   if (!tty_count && !mouse_event_pending()) *rd = 0;
  243.   /* CHFIXME: evt. change interface, select will signal read ok on rd but
  244.      that\'s no totally true (no chars) */
  245. }
  246.  
  247. static int __regargs ttyin_read(void *userinfo, void *buffer, unsigned int length)
  248. {
  249.   amiga_consume_input();
  250.   if (length > tty_count) length = tty_count;
  251.   memcpy(buffer, ttybuf, length);
  252.   tty_count -= length;
  253.   if (tty_count) memmove(ttybuf, ttybuf + length, tty_count - length);
  254.   reset_mouse_event_pending();
  255.   
  256.   return (int)length;
  257. }
  258.  
  259. static int __regargs ttyin_write(void *userinfo, void *buffer, unsigned int length)
  260. {
  261.   errno = EACCES;
  262.   return -1;
  263. }
  264.  
  265. static int __regargs ttyin_lseek(void *userinfo, long rpos, int mode)
  266. {
  267.   errno = ESPIPE;
  268.   return -1;
  269. }
  270.  
  271. static int __regargs ttyin_close(void *userinfo, int internal)
  272. {
  273.   return 0;
  274. }
  275.  
  276. static int __regargs ttyin_ioctl(void *userinfo, int request, void *data)
  277. {
  278.   errno = EINVAL;
  279.   return -1;
  280. }
  281.  
  282. #define CBUFSIZE 1024
  283. #undef fwrite
  284. #undef fflush
  285.  
  286. char cbuffer[CBUFSIZE + 16], *cbuffer_pos;
  287.  
  288. int emacs_fflush(FILE *f)
  289. {
  290.     if (noninteractive || f != stdout) return fflush(f);
  291.     else
  292.     {
  293.     int len;
  294.  
  295.     len = cbuffer_pos - cbuffer;
  296. #ifdef MULTI_FRAME
  297. CHFIXME check
  298. #endif
  299.     if (term_initialised)
  300.         if (!inhibit_window_system) screen_puts(selected_frame, cbuffer, len);
  301.         else serial_puts(cbuffer, len);
  302.     if (termscript) fwrite (cbuffer, 1, len, termscript);
  303.     cbuffer_pos = cbuffer;
  304.  
  305.     return 0;
  306.     }
  307. }
  308.  
  309. void emacs_putchar(int c)
  310. {
  311.     if (cbuffer_pos >= cbuffer + CBUFSIZE) emacs_fflush(stdout);
  312.     *cbuffer_pos++ = c;
  313. }
  314.  
  315. void emacs_output(FRAME_PTR f, char *str, int size)
  316. {
  317.     if (cbuffer_pos + size > cbuffer + CBUFSIZE) emacs_fflush(stdout);
  318.     if (size > CBUFSIZE)
  319.     {
  320.     if (term_initialised)
  321.         if (!inhibit_window_system) screen_puts(f, str, size);
  322.         else serial_puts(str, size);
  323.     }
  324.     else
  325.     {
  326.     memcpy(cbuffer_pos, str, size);
  327.     cbuffer_pos += size;
  328.     }
  329. }
  330.  
  331. void emacs_output_glyphs(FRAME_PTR f, GLYPH *str, int size) /* CHFIXME: we ignore faces for now */
  332. {
  333.     if (cbuffer_pos + size > cbuffer + CBUFSIZE) emacs_fflush(stdout);
  334.     if (size > CBUFSIZE)
  335.     {
  336.     register int i = size, lsize;
  337.     register GLYPH *g = str;
  338.     
  339.     /* CHFIXME */
  340.     while(i)
  341.     {
  342.         if(i < CBUFSIZE)
  343.         lsize = i;
  344.         else
  345.         lsize = CBUFSIZE;
  346.         emacs_output_glyphs(f, g, lsize);
  347.         i -= lsize;
  348.         g += lsize;
  349.     }
  350.     }
  351.     else
  352.     {
  353.     register int i = size;
  354.     register char *s = cbuffer_pos;
  355.     register GLYPH *g = str;
  356.  
  357.     while(i--)
  358.     {
  359.         *s++ = (*g++) & 0xff;
  360.     }
  361.     cbuffer_pos += size;
  362.     }
  363. }
  364.  
  365. void emacs_fwrite(char *str, unsigned int nblocks, unsigned int len, FILE *f)
  366. {
  367.     if (noninteractive || f != stdout) fwrite (str, nblocks, len, f);
  368.     else
  369.     {
  370.     unsigned int size;
  371.  
  372.     if (nblocks == 1) size = len; /* Emacs always uses 1 "block" */
  373.     else size = nblocks * len;
  374. #ifdef MULTI_FRAME
  375.     CHFIXME check
  376. #endif
  377.     emacs_output(selected_frame, str, size);
  378.     }
  379. }
  380.  
  381. void syms_of_amiga_tty(void)
  382. {
  383.   syms_of_amiga_screen();
  384.   syms_of_amiga_rexx();
  385. }
  386.  
  387. void init_amiga_tty()
  388. {
  389.   inputsig = 0;
  390.   term_initialised = FALSE;
  391.   init_amiga_rexx();
  392. }
  393.  
  394. void cleanup_amiga_tty()
  395. {
  396.   cleanup_amiga_rexx();
  397.   cleanup_amiga_serial();
  398.   cleanup_amiga_screen();
  399. }
  400.  
  401. void early_amiga_tty()
  402. {
  403.   cbuffer_pos = cbuffer;
  404.   tty_count = 0;
  405. }
  406.  
  407. void amiga_term_open(void)
  408. {
  409.   inhibit_window_system ? init_amiga_serial() : init_amiga_screen();
  410.   close(0);
  411.   if (_alloc_fd((void *)1, FI_READ, ttyin_select_start, ttyin_select_poll, ttyin_read,
  412.         ttyin_write, ttyin_lseek, ttyin_close, ttyin_ioctl) == 0)
  413.     term_initialised = TRUE;
  414.   else _fail("Failed to initialise I/O, no memory ?");
  415. }
  416.  
  417. /* Set the logical window size associated with descriptor FD
  418.    to HEIGHT and WIDTH.  This is used mainly with ptys.  */
  419.  
  420. int
  421. set_window_size (fd, height, width)
  422.      int fd, height, width;
  423. {
  424.   return -1; /* CHFIXME: where used?, ok? */
  425. }
  426.