size_t cbuf_read_char(cbuf_t *cbuf, char *c, bool block) { DEBUG_ASSERT(cbuf); DEBUG_ASSERT(c); enter_critical_section(); if (block) event_wait(&cbuf->event); // see if there's data available size_t ret = 0; if (cbuf->tail != cbuf->head) { *c = cbuf->buf[cbuf->tail]; cbuf->tail = INC_POINTER(cbuf, cbuf->tail, 1); if (cbuf->tail == cbuf->head) { // we've emptied the buffer, unsignal the event event_unsignal(&cbuf->event); } ret = 1; } exit_critical_section(); return ret; }
size_t cbuf_read(cbuf_t *cbuf, void *_buf, size_t buflen, bool block) { size_t ret; char *buf = (char *)_buf; DEBUG_ASSERT(cbuf); DEBUG_ASSERT(_buf); enter_critical_section(); if (block) event_wait(&cbuf->event); // see if there's data available if (cbuf->tail != cbuf->head) { size_t pos = 0; // loop until we've read everything we need // at most this will make two passes to deal with wraparound while (pos < buflen && cbuf->tail != cbuf->head) { size_t read_len; if (cbuf->head > cbuf->tail) { // simple case where there is no wraparound read_len = MIN(cbuf->head - cbuf->tail, buflen - pos); } else { // read to the end of buffer in this pass read_len = MIN(valpow2(cbuf->len_pow2) - cbuf->tail, buflen - pos); } memcpy(buf + pos, cbuf->buf + cbuf->tail, read_len); cbuf->tail = INC_POINTER(cbuf, cbuf->tail, read_len); pos += read_len; } if (cbuf->tail == cbuf->head) { // we've emptied the buffer, unsignal the event event_unsignal(&cbuf->event); } ret = pos; } else { DEBUG_ASSERT(!block); ret = 0; } exit_critical_section(); return ret; }
size_t cbuf_write_char(cbuf_t *cbuf, char c, bool canreschedule) { DEBUG_ASSERT(cbuf); enter_critical_section(); size_t ret = 0; if (cbuf_space_avail(cbuf) > 0) { cbuf->buf[cbuf->head] = c; cbuf->head = INC_POINTER(cbuf, cbuf->head, 1); ret = 1; if (cbuf->head != cbuf->tail) event_signal(&cbuf->event, canreschedule); } exit_critical_section(); return ret; }
size_t cbuf_write(cbuf_t *cbuf, const void *_buf, size_t len, bool canreschedule) { const char *buf = (const char *)_buf; LTRACEF("len %zd\n", len); DEBUG_ASSERT(cbuf); DEBUG_ASSERT(_buf); DEBUG_ASSERT(len < valpow2(cbuf->len_pow2)); enter_critical_section(); size_t write_len; size_t pos = 0; while (pos < len && cbuf_space_avail(cbuf) > 0) { if (cbuf->head >= cbuf->tail) { write_len = MIN(valpow2(cbuf->len_pow2) - cbuf->head, len - pos); } else { write_len = MIN(cbuf->tail - cbuf->head - 1, len - pos); } // if it's full, abort and return how much we've written if (write_len == 0) { break; } memcpy(cbuf->buf + cbuf->head, buf + pos, write_len); cbuf->head = INC_POINTER(cbuf, cbuf->head, write_len); pos += write_len; } if (cbuf->head != cbuf->tail) event_signal(&cbuf->event, canreschedule); exit_critical_section(); return pos; }
wchar_t inkey(int to, int delay) { wchar_t k; int c, mapping; keymap_t *current = _cursesi_screen->base_keymap; FILE *infd = _cursesi_screen->infd; k = 0; /* XXX gcc -Wuninitialized */ #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "inkey (%d, %d)\n", to, delay); #endif for (;;) { /* loop until we get a complete key sequence */ reread: if (state == INKEY_NORM) { if (delay && __timeout(delay) == ERR) return ERR; c = fgetc(infd); if (c == EOF) { clearerr(infd); return ERR; } if (delay && (__notimeout() == ERR)) return ERR; k = (wchar_t) c; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "inkey (state normal) got '%s'\n", unctrl(k)); #endif working = start; inbuf[working] = k; INC_POINTER(working); end = working; state = INKEY_ASSEMBLING; /* go to the assembling * state now */ } else if (state == INKEY_BACKOUT) { k = inbuf[working]; INC_POINTER(working); if (working == end) { /* see if we have run * out of keys in the * backlog */ /* if we have then switch to assembling */ state = INKEY_ASSEMBLING; } } else if (state == INKEY_ASSEMBLING) { /* assembling a key sequence */ if (delay) { if (__timeout(to ? (ESCDELAY / 100) : delay) == ERR) return ERR; } else { if (to && (__timeout(ESCDELAY / 100) == ERR)) return ERR; } c = fgetc(infd); if (ferror(infd)) { clearerr(infd); return ERR; } if ((to || delay) && (__notimeout() == ERR)) return ERR; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "inkey (state assembling) got '%s'\n", unctrl(k)); #endif if (feof(infd) || c == -1) { /* inter-char timeout, * start backing out */ clearerr(infd); if (start == end) /* no chars in the buffer, restart */ goto reread; k = inbuf[start]; state = INKEY_TIMEOUT; } else { k = (wchar_t) c; inbuf[working] = k; INC_POINTER(working); end = working; } } else { fprintf(stderr, "Inkey state screwed - exiting!!!"); exit(2); } /* * Check key has no special meaning and we have not * timed out and the key has not been disabled */ mapping = current->mapping[k]; if (((state == INKEY_TIMEOUT) || (mapping < 0)) || ((current->key[mapping]->type == KEYMAP_LEAF) && (current->key[mapping]->enable == FALSE))) { /* return the first key we know about */ k = inbuf[start]; INC_POINTER(start); working = start; if (start == end) { /* only one char processed */ state = INKEY_NORM; } else {/* otherwise we must have more than one char * to backout */ state = INKEY_BACKOUT; } return k; } else { /* must be part of a multikey sequence */ /* check for completed key sequence */ if (current->key[current->mapping[k]]->type == KEYMAP_LEAF) { start = working; /* eat the key sequence * in inbuf */ /* check if inbuf empty now */ if (start == end) { /* if it is go back to normal */ state = INKEY_NORM; } else { /* otherwise go to backout state */ state = INKEY_BACKOUT; } /* return the symbol */ return current->key[current->mapping[k]]->value.symbol; } else { /* * Step on to next part of the multi-key * sequence. */ current = current->key[current->mapping[k]]->value.next; } } } }
/* * GetClipboardSavebuf - gets data from the clipboard, and builds a * temporary savebuf from it */ int GetClipboardSavebuf( savebuf *clip ) { GLOBALHANDLE hglob; char _HUGE_ *ptr; char _HUGE_ *cpos; fcb_list fcblist; int i; bool is_flushed; bool has_lf; bool record_done; char ch; int used; if( !openClipboardForRead() ) { return( ERR_CLIPBOARD_EMPTY ); } hglob = GetClipboardData( CF_TEXT ); if( hglob == NULL ) { return( ERR_CLIPBOARD ); } ptr = GetPtrGlobalLock( hglob ); cpos = ptr; i = 0; is_flushed = false; has_lf = false; fcblist.head = NULL; fcblist.tail = NULL; record_done = false; /* * add all characters to ReadBuffer. Each time this fills, * create a new FCB */ while( (ch = *ptr) != '\0' ) { INC_POINTER( ptr ); ReadBuffer[i++] = ch; if( ch == LF ) { has_lf = true; } if( i >= MAX_IO_BUFFER ) { is_flushed = true; used = addAnFcb( &fcblist, i ); ptr = GET_POINTER( cpos, used ); cpos = ptr; i = 0; } } /* * after we are done, see if any characters are left unprocessed */ if( i != 0 ) { /* * check if this is a partial line */ if( !is_flushed && !has_lf ) { clip->type = SAVEBUF_LINE; ReadBuffer[i] = 0; clip->u.data = MemAlloc( i + 1 ); strcpy( clip->u.data, ReadBuffer ); record_done = true; } else { // add LF to end of buffer if( i >= MAX_IO_BUFFER - 2 ) { addAnFcb( &fcblist, i ); i = 0; } ReadBuffer[i++] = CR; ReadBuffer[i++] = LF; addAnFcb( &fcblist, i ); } } else if( !is_flushed ) { clip->type = SAVEBUF_NOP; record_done = true; } if( !record_done ) { clip->type = SAVEBUF_FCBS; clip->u.fcbs.head = fcblist.head; clip->u.fcbs.tail = fcblist.tail; } GlobalUnlock( hglob ); CloseClipboard(); return( ERR_NO_ERR ); } /* GetClipboardSavebuf */
/* * AddFcbsToClipboard - add all lines in a given set of fcbs to the clipboard */ int AddFcbsToClipboard( fcb_list *fcblist ) { fcb *cfcb; line *cline; char _HUGE_ *ptr; long size; int i; GLOBALHANDLE hglob; bool crlf_left_to_write = false; if( !openClipboardForWrite() ) { return( ERR_CLIPBOARD ); } /* * compute the number of bytes in total */ size = 1; // for trailing null char for( cfcb = fcblist->head; cfcb != NULL; cfcb = cfcb->next ) { size += (long)cfcb->byte_cnt + (long)(cfcb->end_line-cfcb->start_line + 1); if( cfcb == fcblist->tail ) { break; } } /* * get the memory to store this stuff */ hglob = GlobalAlloc( GMEM_MOVEABLE, size ); if( hglob == NULL ) { CloseClipboard(); return( ERR_CLIPBOARD ); } ptr = GetPtrGlobalLock( hglob ); if( ptr == NULL ) { CloseClipboard(); return( ERR_CLIPBOARD ); } /* * copy all lines into this pointer */ for( cfcb = fcblist->head; cfcb != NULL; cfcb = cfcb->next ) { FetchFcb( cfcb ); for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) { // one CR,LF left to write? if( crlf_left_to_write ) { // yes: write it crlf_left_to_write = false; *ptr = CR; INC_POINTER( ptr ); *ptr = LF; INC_POINTER( ptr ); } for( i = 0; i < cline->len; i++ ) { *ptr = cline->data[i]; INC_POINTER( ptr ); } // remember to write one CR,LF next time crlf_left_to_write = true; } if( cfcb == fcblist->tail ) { break; } } // the last CR,LF is omitted *ptr = 0; GlobalUnlock( hglob ); SetClipboardData( CF_TEXT, hglob ); CloseClipboard(); return( ERR_NO_ERR ); } /* AddFcbsToClipboard */