Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 1 | /* vi:set ts=8 sts=4 sw=4: |
| 2 | * |
| 3 | * VIM - Vi IMproved by Bram Moolenaar |
| 4 | * BeBox port Copyright 1997 by Olaf Seibert. |
| 5 | * |
| 6 | * Do ":help uganda" in Vim to read copying and usage conditions. |
| 7 | * Do ":help credits" in Vim to see a list of people who contributed. |
| 8 | * See README.txt for an overview of the Vim source code. |
| 9 | */ |
| 10 | /* |
| 11 | * os_beos.c Additional stuff for BeOS (rest is in os_unix.c) |
| 12 | */ |
| 13 | |
| 14 | #include <float.h> |
| 15 | #include <termios.h> |
Bram Moolenaar | 8288149 | 2012-11-20 16:53:39 +0100 | [diff] [blame] | 16 | #ifndef PROTO |
| 17 | # include <kernel/OS.h> |
| 18 | #endif |
| 19 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 20 | #include "vim.h" |
| 21 | |
| 22 | #if USE_THREAD_FOR_INPUT_WITH_TIMEOUT |
| 23 | |
| 24 | #ifdef PROTO /* making prototypes on Unix */ |
| 25 | #define sem_id int |
| 26 | #define thread_id int |
| 27 | #endif |
| 28 | |
| 29 | char_u charbuf; |
| 30 | signed char charcount; |
| 31 | sem_id character_present; |
| 32 | sem_id character_wanted; |
| 33 | thread_id read_thread_id; |
| 34 | |
| 35 | #define TRY_ABORT 0 /* This code does not work so turn it off. */ |
| 36 | |
| 37 | #if TRY_ABORT |
| 38 | static void |
| 39 | mostly_ignore(int sig) |
| 40 | { |
| 41 | } |
| 42 | #endif |
| 43 | |
| 44 | static long |
| 45 | read_thread(void *dummy) |
| 46 | { |
| 47 | signal(SIGINT, SIG_IGN); |
| 48 | signal(SIGQUIT, SIG_IGN); |
| 49 | #if TRY_ABORT |
| 50 | signal(SIGUSR1, mostly_ignore); |
| 51 | #endif |
| 52 | |
| 53 | for (;;) { |
| 54 | if (acquire_sem(character_wanted) != B_NO_ERROR) |
| 55 | break; |
| 56 | charcount = read(read_cmd_fd, &charbuf, 1); |
| 57 | release_sem(character_present); |
| 58 | } |
| 59 | |
| 60 | return 0; |
| 61 | } |
| 62 | |
| 63 | void |
| 64 | beos_cleanup_read_thread(void) |
| 65 | { |
| 66 | if (character_present > 0) |
| 67 | delete_sem(character_present); |
| 68 | character_present = 0; |
| 69 | if (read_thread_id > 0) |
| 70 | kill_thread(read_thread_id); |
| 71 | read_thread_id = 0; |
| 72 | } |
| 73 | |
| 74 | #endif |
| 75 | |
| 76 | /* |
| 77 | * select() emulation. Hopefully, in DR9 there will be something |
| 78 | * useful supplied by the system. ... Alas, not. Not in AAPR, nor |
| 79 | * in PR or even PR2... R3 then maybe? I don't think so! |
| 80 | */ |
| 81 | |
| 82 | int |
| 83 | beos_select(int nbits, |
| 84 | struct fd_set *rbits, |
| 85 | struct fd_set *wbits, |
| 86 | struct fd_set *ebits, |
| 87 | struct timeval *timeout) |
| 88 | { |
| 89 | bigtime_t tmo; |
| 90 | |
| 91 | if (nbits == 0) { |
| 92 | /* select is purely being used for delay */ |
| 93 | snooze(timeout->tv_sec * 1e6 + timeout->tv_usec); |
| 94 | return 0; |
| 95 | } |
| 96 | #if 0 |
| 97 | /* |
| 98 | * This does not seem to work either. Reads here are not supposed to |
| 99 | * block indefinitely, yet they do. This is most annoying. |
| 100 | */ |
| 101 | if (FD_ISSET(0, rbits)) { |
| 102 | char cbuf[1]; |
| 103 | int count; |
| 104 | struct termios told; |
| 105 | struct termios tnew; |
| 106 | tcgetattr(0, &told); |
| 107 | tnew = told; |
| 108 | tnew.c_lflag &= ~ICANON; |
| 109 | tnew.c_cc[VMIN] = 0; |
| 110 | tnew.c_cc[VTIME] = timeout->tv_sec * 10 + timeout->tv_usec / 100000; |
| 111 | tcsetattr(0, TCSANOW, &tnew); |
| 112 | |
| 113 | count = read(0, &cbuf, sizeof(cbuf)); |
| 114 | tcsetattr(0, TCSANOW, &told); |
| 115 | if (count > 0) { |
| 116 | add_to_input_buf(&cbuf[0], count); |
| 117 | return 1; |
| 118 | } |
| 119 | return 0; |
| 120 | } |
| 121 | #endif |
| 122 | #if USE_THREAD_FOR_INPUT_WITH_TIMEOUT |
| 123 | /* |
| 124 | * Check if the operation is really on stdin... |
| 125 | */ |
| 126 | if (FD_ISSET(read_cmd_fd, rbits)) |
| 127 | { |
| 128 | int acquired; |
| 129 | |
| 130 | /* |
| 131 | * Is this the first time through? |
| 132 | * Then start up the thread and initialise the semaphores. |
| 133 | */ |
| 134 | if (character_present == 0) { |
| 135 | character_present = create_sem(0, "vim character_present"); |
| 136 | character_wanted = create_sem(1, "vim character_wanted"); |
| 137 | read_thread_id = spawn_thread(read_thread, "vim async read", |
| 138 | B_NORMAL_PRIORITY, NULL); |
| 139 | atexit(beos_cleanup_read_thread); |
| 140 | resume_thread(read_thread_id); |
| 141 | } |
| 142 | |
| 143 | /* timeout == NULL means "indefinitely" */ |
| 144 | if (timeout) { |
| 145 | tmo = timeout->tv_sec * 1e6 + timeout->tv_usec; |
| 146 | /* 0 means "don't wait, which is impossible to do exactly. */ |
| 147 | if (tmo == 0) |
| 148 | tmo = 1.0; |
| 149 | } |
| 150 | #if TRY_ABORT |
| 151 | release_sem(character_wanted); |
| 152 | #endif |
| 153 | if (timeout) |
| 154 | acquired = acquire_sem_etc(character_present, 1, B_TIMEOUT, tmo); |
| 155 | else |
| 156 | acquired = acquire_sem(character_present); |
| 157 | if (acquired == B_NO_ERROR) { |
| 158 | if (charcount > 0) { |
| 159 | add_to_input_buf(&charbuf, 1); |
| 160 | #if !TRY_ABORT |
| 161 | release_sem(character_wanted); |
| 162 | #endif |
| 163 | |
| 164 | return 1; |
| 165 | } else { |
| 166 | #if !TRY_ABORT |
| 167 | release_sem(character_wanted); |
| 168 | #endif |
| 169 | |
| 170 | return 0; |
| 171 | } |
| 172 | } |
| 173 | #if TRY_ABORT |
| 174 | else { |
| 175 | /* |
| 176 | * Timeout occurred. Break the read() call by sending |
| 177 | * a signal. Problem: it may be just read()ing it now. |
| 178 | * Therefore we still have to finish the handshake with |
| 179 | * the thread and maybe remember the character. |
| 180 | */ |
| 181 | kill(read_thread_id, SIGUSR1); |
| 182 | /* |
| 183 | * If some other error occurred, don't hang now. |
| 184 | * (We will most likely hang later anyway...) |
| 185 | */ |
| 186 | if (acquired == B_TIMED_OUT) |
| 187 | acquire_sem(character_present); |
| 188 | if (charcount > 0) { |
| 189 | add_to_input_buf(&charbuf, 1); |
| 190 | return 1; |
| 191 | } |
| 192 | return 0; |
| 193 | } |
| 194 | #endif |
| 195 | } |
| 196 | #endif |
| 197 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 198 | return 0; |
| 199 | } |
| 200 | |