home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / EmacsTeX / Emacs-3.0.1 / Source / display.pswm < prev    next >
Encoding:
Text File  |  1995-06-12  |  12.2 KB  |  547 lines

  1. /* Postscript code for terminal emulator.
  2.  
  3.    For legal stuff see the file COPYRIGHT.  */
  4.  
  5. #import <appkit/Application.h>
  6. #import <appkit/Pasteboard.h>
  7. #import <appkit/publicWraps.h>
  8. #import <libc.h>
  9. #import <stdlib.h>
  10.  
  11. #import "EtermView.h"
  12.  
  13. /* 2.0 doesn't do transparency in windows correctly.  */
  14. #define TRANSPARENCYBUG
  15.  
  16. #define NORMAL 0
  17. #define PREFIX 1
  18. #define SECOND_PREFIX 2
  19. #define ESCAPE 3
  20. #define STRING 4
  21. #define STRING_FUNCTION 5
  22. #define Ctl(a) ((a) & 0x1f)
  23.  
  24. struct display
  25. {
  26.   EtermView *view;
  27.   int cursor_x, cursor_y;
  28.   int state;
  29.   int insert_mode, standout_mode;
  30.   int prefix, second_prefix;
  31.   char *string_buffer;
  32.   int string_buffer_len;
  33.   int string_char;
  34. };
  35.  
  36. /* Create the information necessary for handling a new display.  The return
  37.    value is the "rock" that should be given to DPSAddFD () as the value to
  38.    give to input_from_emacs ()
  39.  
  40.    (A "rock" is the CMU term for an item you hide information underneath.)  */
  41. void *
  42. new_display_rock (EtermView *view)
  43. {
  44.   struct display *new_display;
  45.  
  46.   new_display = malloc (sizeof (struct display));
  47.   if (!new_display)
  48.     {
  49.       fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  50.       exit (1);
  51.     }
  52.  
  53.   new_display->view = view;
  54.   new_display->cursor_x = new_display->cursor_y = 0;
  55.   new_display->state = NORMAL;
  56.   new_display->prefix = new_display->second_prefix = 0;
  57.   new_display->string_buffer_len = 1024;
  58.   new_display->string_buffer = malloc(1024);
  59.   if (!new_display->string_buffer)
  60.     {
  61.       fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  62.       exit (1);
  63.     }
  64.   new_display->string_char = 0;
  65.  
  66.   return (void *) new_display;
  67. }
  68.  
  69. defineps static setup()
  70. 0 setgray
  71. emacs:fixedfont setfont
  72. endps
  73.  
  74. #ifdef TRANSPARENCYBUG
  75. #define white_rect(x, y, w, h) clear_rect(x, y, w, h)
  76.  
  77. defineps static clear_rect(int x, y, w, h)
  78. 1 setgray
  79. x y w h rectfill
  80. 0 setgray
  81. endps
  82.  
  83. defineps static grey_rect(int x, y, w, h)
  84. 0.6666 setgray
  85. x y w h rectfill
  86. 0 setgray
  87. endps
  88.  
  89. defineps static show_cursor(int x, y, w, h)
  90. x y w h Highlight compositerect
  91. endps
  92.  
  93. #else /* TRANSPARENCYBUG */
  94.  
  95. defineps static white_rect(int x, y, w, h)
  96. 1 setgray
  97. x y w h rectfill
  98. 0 setgray
  99. endps
  100.  
  101. defineps static clear_rect(int x, y, w, h)
  102. x y w h Clear compositerect
  103. endps
  104.  
  105. defineps static grey_rect(int x, y, w, h)
  106. 0.333 setalpha
  107. x y w h rectfill
  108. 1 setalpha
  109. endps
  110.  
  111. defineps static show_cursor(int x, y, w, h)
  112. x y w h Xor compositerect
  113. endps
  114.  
  115. #endif /* TRANSPARENCY_BUG */
  116.  
  117. defineps static copy_rect(int sx, sy, dx, dy, w, h)
  118. sx sy w h gstate dx dy Copy composite
  119. endps
  120.  
  121. defineps static draw_string(int x, y; char s[n]; int n)
  122. x y moveto
  123. (s) show
  124. endps
  125.  
  126. defineps obscure_cursor()
  127. obscurecursor
  128. endps
  129.  
  130. defineps fix_font(int width)
  131. currentfont dup dup
  132. dup /FontMatrix get 0 get 1 exch div width mul /newwidth exch def
  133. length 1 add dict /newfntdict exch def
  134.  { 1 index /FID ne
  135.   {newfntdict 3 1 roll put}
  136.   {pop pop}
  137.  ifelse
  138.  } forall
  139. /CharStrings get
  140. dup length dict exch
  141.  { pop 1 index exch newwidth put }
  142.  forall
  143. newfntdict /Metrics 3 -1 roll put
  144. /emacs:fixedfont /fixedfont newfntdict definefont def
  145. endps
  146.  
  147. defineps set_font()
  148. /emacs:fixedfont currentfont def
  149. endps
  150.  
  151. static void
  152. invalid ()
  153. {
  154. #ifdef DEBUG
  155.   abort();
  156. #endif
  157. }
  158.  
  159. #define POS_X(a) (SIZE_X (a) + BORDER_WIDTH)
  160. #define POS_Y(a) (SIZE_Y (a) + BORDER_WIDTH)
  161. #define SIZE_X(a) ((int) ((a) * fontWidth))
  162. #define SIZE_Y(a) ((int) ((a) * fontHeight))
  163.  
  164. void
  165. input_from_emacs (int fd, void *rock)
  166. {
  167.   struct display *display = (struct display *) rock;
  168.   int screen_x, screen_y;
  169.   int fontHeight, fontWidth;
  170.   int fontDescender;
  171.   char buf[1024+1];
  172.   int n;
  173.   register char c;
  174.   EtermView *view = display->view;
  175.   int cursor_x = display->cursor_x, cursor_y = display->cursor_y;
  176.   int state = display->state;
  177.   int insert_mode = display->insert_mode;
  178.   int standout_mode = display->standout_mode;
  179.   int prefix = display->prefix, second_prefix = display->second_prefix;
  180.   int string_buffer_len = display->string_buffer_len;
  181.   int string_char = display->string_char;
  182.   int x;
  183.  
  184.   n = read(fd, buf, sizeof (buf) - 1);
  185.   if (n <= 0) {
  186.     if (errno == EWOULDBLOCK) return;
  187.     [NXApp terminate: nil];
  188.   }
  189.  
  190.   [view emacsOn];
  191.   [view lockFocus];
  192.   [view getDimensions: &screen_y : &screen_x];
  193.   [view getDisplayFont: &fontHeight : &fontWidth : &fontDescender];
  194.  
  195.   setup ();
  196.  
  197.   /* Remove old cursor */
  198.   show_cursor(POS_X (cursor_x), POS_Y (cursor_y), fontWidth, fontHeight);
  199.  
  200.   for (x = 0; x < n; x++)
  201.     {
  202.       if ((c = buf[x]) == '\0' && state != STRING)
  203.     continue;
  204.       switch (state)
  205.     {
  206.     case NORMAL:
  207.       if (c >= ' ')
  208.         {
  209.           /* So we print deletes.  Big deal.  */
  210.           int start = x;
  211.           int count;
  212.           int do_newline;
  213.  
  214.           while (++x < n && buf[x] >= ' ');
  215.  
  216.           while (count = x - start)
  217.         {
  218.           if (do_newline = (count + cursor_x >= screen_x))
  219.             count = screen_x - cursor_x;
  220.  
  221.           if (insert_mode)
  222.             {
  223.               copy_rect (POS_X (cursor_x), POS_Y (cursor_y),
  224.                  POS_X (cursor_x + count), POS_Y (cursor_y),
  225.                  SIZE_X (screen_x - cursor_x - count),
  226.                  SIZE_Y (1));
  227.             }
  228.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  229.                   SIZE_X (count), SIZE_Y (1));
  230.  
  231.           if (standout_mode)
  232.             grey_rect (POS_X (cursor_x), POS_Y (cursor_y),
  233.                    SIZE_X (count), SIZE_Y (1));
  234.  
  235.           draw_string (POS_X (cursor_x),
  236.                    POS_Y (cursor_y+1) - (int) fontDescender,
  237.                    &buf[start], count);
  238.  
  239.           start += count;
  240.           if (do_newline)
  241.             {
  242.               cursor_x = 0;
  243.               cursor_y++;
  244.             }
  245.           else
  246.             cursor_x += count;
  247.         }
  248.           --x;
  249.           break;
  250.         }
  251.       switch (c)
  252.         {
  253.         case Ctl ('a'):
  254.         case Ctl ('m'):
  255.           /* Emacs outputs a '\r' on exiting --jgm */
  256.           cursor_x = 0;
  257.           break;
  258.         case Ctl ('b'):
  259.           if (cursor_x > 0)
  260.         --cursor_x;
  261.           break;
  262. #if 0
  263.         case Ctl ('c'):
  264.           do_paste (0);
  265.           break;
  266.         case Ctl ('e'):
  267.           if (EventChannel != -1)
  268.         transmitting_events = TRUE;
  269.           break;
  270. #endif
  271.         case Ctl ('f'):
  272.           if (++cursor_x >= screen_x)
  273.         cursor_x = 0;
  274.           break;
  275.         case Ctl ('g'):
  276.           NXBeep ();
  277.           break;
  278. #if 0
  279.         case Ctl ('h'):
  280.           if (cursor_x > 0)
  281.         {
  282.           --cursor_x;
  283.           delete_chars (1);
  284.         }
  285.           break;
  286. #endif
  287.         case Ctl ('i'):
  288.           insert_mode = !insert_mode;
  289.           break;
  290.         case Ctl ('j'):
  291.           cursor_x = 0;
  292.           cursor_y++;
  293.           break;
  294.         case Ctl ('k'):
  295.           /* clear_to_end_of_line (); */
  296.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  297.               SIZE_X (screen_x - cursor_x), SIZE_Y (1));
  298.           break;
  299. #if 0
  300.         case Ctl ('l'):
  301.           do_redraw ();
  302.           break;
  303. #endif
  304.         case Ctl ('n'):
  305.           if (cursor_y < screen_y)
  306.         cursor_y++;
  307.           break;
  308.         case Ctl ('p'):
  309.           if (cursor_y > 0)
  310.         --cursor_y;
  311.           break;
  312.         case Ctl ('q'):
  313.           state = STRING;
  314.           string_char = 0;
  315.           break;
  316.         case Ctl ('s'):
  317.           standout_mode = !standout_mode;
  318.           break;
  319.         case Ctl ('u'):
  320.           prefix = 0;
  321.           state = PREFIX;
  322.           break;
  323. #if 0
  324.         case Ctl ('y'):
  325.           wm_GiveupInputFocus();
  326.           break;
  327.         case Ctl ('z'):
  328.           [NXApp hide:view];
  329.           break;
  330. #endif
  331.         case Ctl ('['):
  332.           state = ESCAPE;
  333.           break;
  334.         case Ctl ('t'):
  335.           /* Not implemented yet. Besides, no one will ever use it.  */
  336.         default:
  337.           invalid ();
  338.           break;
  339.         }
  340.       break;
  341.     case PREFIX:
  342.       switch (c)
  343.         {
  344.         case '0': case '1': case '2': case '3': case '4':
  345.         case '5': case '6': case '7': case '8': case '9':
  346.           prefix = prefix * 10 + c - '0';
  347.           break;
  348.         case '-':
  349.           prefix = -prefix;
  350.           break;
  351. #if 0
  352.         case Ctl ('a'):
  353.           transmitting_events = FALSE;
  354.           close (EventChannel);
  355.           EventChannel = -1;
  356.           goto normal_state;
  357.         case Ctl ('c'):
  358.           do_paste (prefix);
  359.           goto normal_state;
  360. #endif
  361.         case Ctl ('d'):
  362.           if (prefix > 0)
  363.         {
  364.           /* Delete_chars (prefix); */
  365.           copy_rect (POS_X (cursor_x + prefix), POS_Y (cursor_y),
  366.                  POS_X (cursor_x), POS_Y (cursor_y),
  367.                  SIZE_X (screen_x - cursor_x - 1), SIZE_Y (1));
  368.           clear_rect (POS_X (screen_x - prefix), POS_Y (cursor_y),
  369.                   SIZE_X (prefix), SIZE_Y (1));
  370.         }
  371.           goto normal_state;
  372. #if 0
  373.         case Ctl ('e'):
  374.           transmitting_events = FALSE;
  375.           goto normal_state;
  376. #endif
  377.         case Ctl ('k'):
  378.           if (prefix > 0)
  379.         {
  380.           /* Delete_lines (prefix); */
  381.           copy_rect (POS_X (0), POS_Y (cursor_y + prefix),
  382.                  POS_X (0), POS_Y (cursor_y),
  383.                  SIZE_X (screen_x),
  384.                  SIZE_Y (screen_y - cursor_y - prefix));
  385.           clear_rect (POS_X (0), POS_Y (screen_y - prefix),
  386.                   SIZE_X (screen_x), SIZE_Y (prefix));
  387.         }
  388.           goto normal_state;
  389.         case Ctl ('o'):
  390.           if (prefix > 0)
  391.         {
  392.           /* Insert_lines (prefix); */
  393.           copy_rect (POS_X (0), POS_Y (cursor_y),
  394.                  POS_X (0), POS_Y (cursor_y + prefix),
  395.                  SIZE_X (screen_x),
  396.                  SIZE_Y (screen_y - cursor_y - prefix));
  397.           clear_rect (POS_X (0), POS_Y (cursor_y),
  398.                   SIZE_X (screen_x), SIZE_Y (prefix));
  399.         }
  400.           goto normal_state;
  401.         case Ctl ('q'):
  402.           state = STRING;
  403.           string_char = 0;
  404.           break;
  405.         case Ctl ('u'):
  406.           second_prefix = 0;
  407.           state = SECOND_PREFIX;
  408.           break;
  409.         case '_':
  410.           /* Insert_spaces (prefix); */
  411.           if (prefix > 0)
  412.         {
  413.           copy_rect (POS_X (cursor_x), POS_Y (cursor_y),
  414.                  POS_X (cursor_x + prefix), POS_Y (cursor_y),
  415.                  SIZE_X (screen_x - cursor_x - prefix),
  416.                  SIZE_Y (1));
  417.           clear_rect (POS_X (cursor_x), POS_Y (cursor_y),
  418.                   SIZE_X (prefix), SIZE_Y (1));
  419.         }
  420.           goto normal_state;
  421.         case '.':
  422.           cursor_x = prefix < screen_x ? prefix : 0;
  423.           goto normal_state;
  424.         default:
  425.           invalid ();
  426.         normal_state:
  427.           state = NORMAL;
  428.           break;
  429.         }
  430.       break;
  431.     case SECOND_PREFIX:
  432.       switch (c)
  433.         {
  434.         case '0': case '1': case '2': case '3': case '4':
  435.         case '5': case '6': case '7': case '8': case '9':
  436.           second_prefix = second_prefix * 10 + c - '0';
  437.           break;
  438.         case '.':
  439.           cursor_x = second_prefix < screen_x ? second_prefix : 0;
  440.           cursor_y = prefix < screen_y ? prefix : 0;
  441.           state = NORMAL;
  442.           break;
  443.         default:
  444.           invalid ();
  445.           state = NORMAL;
  446.           break;
  447.         }
  448.       break;
  449.     case ESCAPE:
  450.       switch (c)
  451.         {
  452.         case 'c':
  453.           /* clear_screen (); */
  454.           white_rect (0, 0, SIZE_X (screen_x) + 2 * BORDER_WIDTH,
  455.               SIZE_Y(screen_y) + 2 * BORDER_WIDTH);
  456. #ifndef TRANSPARENCYBUG
  457.           clear_rect (POS_X (0), POS_Y (0),
  458.               SIZE_X (screen_x), SIZE_Y (screen_y));
  459. #endif
  460.           cursor_x = cursor_y = 0;
  461.           insert_mode = standout_mode = 0;
  462.           break;
  463.         case 'k':
  464.           /* Clear_to_end_of_screen (); */
  465.           clear_rect (POS_X (0), POS_Y (cursor_y),
  466.               SIZE_X (screen_x), SIZE_Y (screen_y - cursor_y));
  467.           break;
  468.         default:
  469.           invalid ();
  470.           break;
  471.         }
  472.       state = NORMAL;
  473.       break;
  474.     case STRING:
  475.       if (string_char == string_buffer_len)
  476.         {
  477.           string_buffer_len += 1024;
  478.           display->string_buffer = realloc(display->string_buffer,
  479.                            string_buffer_len);
  480.           if (!display->string_buffer)
  481.         {
  482.           fprintf (stderr, "Emacs: Virtual memory exhausted\n");
  483.           exit (1);
  484.         }
  485.         }
  486.       if ((display->string_buffer[string_char++] = c) == '\377')
  487.         state = STRING_FUNCTION;
  488.       break;
  489.     case STRING_FUNCTION:
  490.       {
  491.         display->string_buffer[--string_char] = '\0';
  492.         switch (c)
  493.           {
  494.           case 'c':
  495.         {
  496.           id    pBoard = [view pasteboard];
  497.           [pBoard declareTypes:&NXAsciiPboardType num:1
  498.               owner:NULL];
  499.           [pBoard writeType:NXAsciiPboardType 
  500.               data:display->string_buffer length:string_char];
  501.           [view pasteboardWritten];
  502.           break;
  503.         }
  504. #if 0
  505.           case 'e':
  506.         write (MasterChannel, display->string_buffer, string_char);
  507.         break;
  508.           case 'f':
  509.         change_font (display->string_buffer);
  510.         do_redraw ();
  511.         break;
  512. #endif
  513.           case 't':
  514.         [view setTitle: display->string_buffer];
  515.         break;
  516. #if 0
  517.           case 'p':
  518.         wm_SetProgramName (display->string_buffer);
  519.         break;
  520.           case 'm':
  521.         wm_AddMenu (display->string_buffer);
  522.         break;
  523. #endif
  524.           default:
  525.         invalid();
  526.         break;
  527.           }
  528.         state = NORMAL;
  529.       }
  530.     }
  531.     }
  532.  
  533.   /* Display cursor */
  534.   show_cursor (POS_X (cursor_x), POS_Y (cursor_y), fontWidth, fontHeight);
  535.  
  536.   [view unlockFocus];
  537.   display->cursor_x = cursor_x;
  538.   display->cursor_y = cursor_y;
  539.   display->state = state;
  540.   display->insert_mode = insert_mode;
  541.   display->standout_mode = standout_mode;
  542.   display->prefix = prefix;
  543.   display->second_prefix = second_prefix;
  544.   display->string_buffer_len = string_buffer_len;
  545.   display->string_char = string_char;
  546. }
  547.