terminal.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (C) 2003 Mooffie <mooffie@typo.co.il>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  16. #include <config.h>
  17. // Baruch says to put editor.h first.
  18. #include "editor.h" // for SIGHUP's emergency_save
  19. #include "terminal.h"
  20. #include "dbg.h"
  21. #include <unistd.h> // _POSIX_VDISABLE
  22. #include <sys/wait.h> // wait()
  23. #include <signal.h>
  24. #include <errno.h>
  25. #include <termios.h>
  26. #include <stdlib.h> // getenv
  27. #include <sys/time.h> // timeval
  28. #include <string.h> // strstr
  29. #ifdef HAVE_LANGINFO_CODESET
  30. # include <langinfo.h>
  31. #endif
  32. bool terminal::initialized = false;
  33. bool terminal::is_utf8;
  34. bool terminal::force_iso88598;
  35. bool terminal::is_fixed;
  36. bool terminal::is_color;
  37. bool terminal::use_default_colors;
  38. bool terminal::do_arabic_shaping;
  39. bool terminal::graphical_boxes;
  40. static termios oldterm;
  41. void terminal::finish()
  42. {
  43. endwin();
  44. tcsetattr(0, TCSANOW, &oldterm);
  45. DBG(1, ("Bailing out\n"));
  46. }
  47. static RETSIGTYPE sigint_hndlr(int sig)
  48. {
  49. }
  50. static RETSIGTYPE sigterm_hndlr(int sig)
  51. {
  52. terminal::finish();
  53. exit(0);
  54. }
  55. static RETSIGTYPE sighup_hndlr(int sig)
  56. {
  57. Editor::get_global_instance()->emergency_save();
  58. DBG(1, ("SIGHUP HANDLER\n"));
  59. exit(0);
  60. }
  61. static RETSIGTYPE sigchld_hndlr(int sig)
  62. {
  63. int serrno = errno;
  64. wait(NULL);
  65. errno = serrno;
  66. }
  67. // was_ctrl_c_pressed() - is a crude method to check if ^C was pressed
  68. // while in a non-interactive segment, like when receiving data from
  69. // the speller. it uses select() to see if there's any keyboard (stdin)
  70. // input available. If so, it eats it up, and checks whether 0x03 (^C)
  71. // was encountered.
  72. bool terminal::was_ctrl_c_pressed()
  73. {
  74. #define HAVE_SELECT 1
  75. #ifdef HAVE_SELECT
  76. fd_set rfds;
  77. timeval tv;
  78. tv.tv_sec = 0;
  79. tv.tv_usec = 0;
  80. bool ctrl_c_pressed = false;
  81. while (1) {
  82. FD_ZERO(&rfds);
  83. FD_SET(STDIN_FILENO, &rfds);
  84. if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) <= 0)
  85. break; // no kbd input avail.
  86. char ch;
  87. read(STDIN_FILENO, &ch, 1);
  88. if (ch == '\x03' || ch == '\x07')
  89. ctrl_c_pressed = true;
  90. }
  91. return ctrl_c_pressed;
  92. #else
  93. return false;
  94. #endif
  95. }
  96. // DISABLE_SIGTSTP() is used by child processes (e.g. the speller)
  97. // to get rid of ncurses' handler. See TODO.
  98. void DISABLE_SIGTSTP()
  99. {
  100. signal(SIGTSTP, SIG_IGN);
  101. }
  102. void terminal::init()
  103. {
  104. tcgetattr(0, &oldterm);
  105. #ifdef _POSIX_VDISABLE
  106. termios term;
  107. term = oldterm;
  108. term.c_cc[VINTR] = _POSIX_VDISABLE;
  109. term.c_cc[VQUIT] = _POSIX_VDISABLE;
  110. term.c_cc[VSTOP] = _POSIX_VDISABLE;
  111. term.c_cc[VSTART] = _POSIX_VDISABLE;
  112. tcsetattr(0, TCSANOW, &term);
  113. #else
  114. termios term;
  115. term = oldterm;
  116. term.c_lflag &= ~ISIG;
  117. term.c_iflag &= ~(IXON | IXOFF);
  118. tcsetattr(0, TCSANOW, &term);
  119. #endif
  120. signal(SIGINT, sigint_hndlr);
  121. signal(SIGTERM, sigterm_hndlr);
  122. signal(SIGHUP, sighup_hndlr);
  123. signal(SIGCHLD, sigchld_hndlr);
  124. // it's important to ignore SIGPIPE because the editor has the ability
  125. // to write to a pipe.
  126. signal(SIGPIPE, SIG_IGN);
  127. initscr();
  128. keypad(stdscr, TRUE);
  129. nonl();
  130. cbreak();
  131. noecho();
  132. #ifdef HAVE_COLOR
  133. if (has_colors()) {
  134. is_color = true;
  135. start_color();
  136. #ifdef HAVE_USE_DEFAULT_COLORS
  137. terminal::use_default_colors = (::use_default_colors() == OK);
  138. #else
  139. terminal::use_default_colors = false;
  140. #endif
  141. } else {
  142. is_color = false;
  143. }
  144. #else
  145. is_color = false;
  146. #endif
  147. terminal::do_arabic_shaping = false;
  148. terminal::initialized = true;
  149. if (under_x11())
  150. terminal::graphical_boxes = true;
  151. else
  152. terminal::graphical_boxes = false;
  153. }
  154. bool terminal::is_interactive()
  155. {
  156. return initialized;
  157. }
  158. // Are we running under X?
  159. bool terminal::under_x11()
  160. {
  161. return getenv("DISPLAY") && *getenv("DISPLAY");
  162. }
  163. // determine_locale() - find out the currently used locale.
  164. void terminal::determine_locale()
  165. {
  166. const char *locale;
  167. (void) (((locale = getenv("LC_ALL")) && *locale) ||
  168. ((locale = getenv("LC_CTYPE")) && *locale) ||
  169. ((locale = getenv("LANG"))));
  170. is_utf8 = false;
  171. #ifdef HAVE_LANGINFO_CODESET
  172. # define lcl(subs) strstr(nl_langinfo(CODESET), subs)
  173. #else
  174. # define lcl(subs) (locale && strstr(locale, subs))
  175. #endif
  176. if (lcl("UTF-8") || lcl("utf-8") || lcl("UTF8") || lcl("utf8"))
  177. is_utf8 = true;
  178. // we assume this is a non-fixed terminal if and only if we are in
  179. // UTF-8 locale and a DISPLAY environment variable is present (the
  180. // user can change this with command-line options).
  181. is_fixed = !(is_utf8 && under_x11());
  182. }