Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c
- index 0f72795..5568a7b 100644
- --- a/code/client/cl_keys.c
- +++ b/code/client/cl_keys.c
- @@ -33,6 +33,9 @@ int nextHistoryLine; // the last line in the history buffer, not masked
- int historyLine; // the line being displayed from history buffer
- // will be <= nextHistoryLine
- +// For now, only support 1 kill ring.
- +killring_t killRing;
- +
- field_t g_consoleField;
- field_t chatField;
- qboolean chat_team;
- @@ -394,7 +397,80 @@ void Field_BigDraw( field_t *edit, int x, int y, int width, qboolean showCursor,
- /*
- ================
- +Add_Kill_Ring_Entry
- +
- +This isn't a kill ring as much as a kill buffer currently.
- +It adds the last kill to a buffer so the user can yank it later.
- +The killring buffer is guaranteed to be NUL terminated if it is used.
- +================
- +*/
- +static void Add_Kill_Ring_Entry(const char *s, int start, int end)
- +{
- + int num_elements = end - start + 1;
- +
- + // MAX_EDIT_LINE - 1 is also an invalid index because we need room for the NUL
- + if (start > end || start < 0 || end < 0 || end >= MAX_EDIT_LINE - 1) {
- + return;
- + }
- +
- + // copy line to history buffer. This is always NUL terminated.
- + memmove(killRing.buffer, s + start, num_elements);
- + killRing.length = num_elements;
- +
- + // Minimum is 1 and max is MAX_EDIT_LINE - 1.
- + killRing.buffer[num_elements] = '\0';
- +}
- +
- +/*
- +================
- +Use_Kill_Ring_Entry
- +
- +This uses the last (currently only) kill from the buffer and inserts it.
- +It will NUL terminate the resulting string and stays within the bounds of the buffer.
- +It silently truncates as needed.
- +================
- +*/
- +static void Use_Kill_Ring_Entry(field_t *edit)
- +{
- + size_t len;
- + size_t num_bytes;
- + int copied = 0;
- + char cache[MAX_EDIT_LINE];
- +
- + // MAX_EDIT_LINE - 1 is an invalid index because we need room for the NUL
- + if (edit->cursor < 0 || edit->cursor >= MAX_EDIT_LINE - 1) {
- + return;
- + }
- +
- + // Save the current buffer after the cursor. Any space left after the
- + // kill buffer will use this data.
- + memmove(cache, edit->buffer, sizeof(cache));
- +
- + // num_bytes uses MAX_EDIT_LINE without -1 because strlcpy handles size-1 and
- + // edit->cursor without + 1 because we're overwriting edit->cursor's position.
- + num_bytes = MAX_EDIT_LINE - edit->cursor;
- +
- + // Copy the contents of the kill buffer that fit
- + if ((len = Q_strlcpy(edit->buffer + edit->cursor, killRing.buffer, num_bytes)) >= num_bytes) {
- + // Truncated
- + copied = edit->cursor + num_bytes;
- + } else {
- + copied = edit->cursor + len;
- + }
- +
- + // Concatenate the left over parts that fit
- + if ((len = Q_strlcat(edit->buffer + edit->cursor, cache + edit->cursor, num_bytes)) >= num_bytes) {
- + /* Silently handle truncation? */
- + }
- +
- + edit->cursor = copied;
- +}
- +
- +/*
- +================
- Field_Paste
- +
- +Pastes the clipboard data for platforms that define Sys_GetClipboardData().
- ================
- */
- void Field_Paste( field_t *edit ) {
- @@ -417,6 +493,553 @@ void Field_Paste( field_t *edit ) {
- }
- /*
- +==================
- +Field_Kill_Text
- +
- +This kills text spanning the start to end indices. It shifts the results
- +left and fills in any left over areas with NULs.
- +
- +Example using mark which isn't available yet in this code. It is in GNU Emacs.
- +Treat the mark as the starting spot and the cursor as the end.
- +
- +Unlike Emacs, this includes the last element in the selection. This is because
- +the cursor here is referring to an actual element in the array. In Emacs, it
- +refers to the position between characters.
- +
- + m------------------- mark
- + v------------ cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------------------- cursor
- +orig$ ls /etrg.conf
- +==================
- +*/
- +static void Field_Kill_Text( field_t *edit, int start, int end ) {
- + int num_moved;
- +
- + // If the user sent it in the wrong order, swap them.
- + if (start > end) {
- + int old = start;
- + start = end;
- + end = old;
- + }
- +
- + // MAX_EDIT_LINE - 1 is invalid because that's for the NUL.
- + if (start < 0 || end < 0 || end >= MAX_EDIT_LINE - 1) {
- + return;
- + }
- +
- + // Add this text to the kill ring so we can yank it out later.
- + Add_Kill_Ring_Entry(edit->buffer, start, end);
- +
- + // MAX_EDIT_LINE - 1 is the last index of the array. It must be a NUL.
- + // Therefore, MAX_EDIT_LINE - 2 is the last array element that has user data.
- + // With the check above, end will be at most the index before the NUL.
- + num_moved = MAX_EDIT_LINE - 2 - end;
- + memmove(edit->buffer + start, edit->buffer + end + 1, num_moved);
- +
- + // num_moved is not zero indexed so this will be 1 beyond what we moved.
- + memset(edit->buffer + start + num_moved, 0, MAX_EDIT_LINE - start - num_moved);
- +
- + edit->cursor = start;
- +}
- +
- +/*
- +==================
- +Field_Kill
- +
- +Kills the line from the current cursor position to the end of the line.
- +
- +It should kill the entire line if it is at the beginning. It should not do
- +anything if it is at the end of the line.
- +
- +Example from bash (GNU Readline):
- +
- + v---------------- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v---------------- cursor
- +modi$ ls /etc/X
- +
- + v------------------------- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------------------------- cursor
- +modi$
- +
- + v---- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v---- cursor
- +modi$ ls /etc/X11/xorg.conf
- +==================
- +*/
- +static void Field_Kill_Line( field_t *edit ) {
- + size_t len;
- + if (edit->cursor < 0) {
- + return;
- + }
- +
- + // Use strlen rather than until the end of the buffer because
- + // we save the killed region in a buffer.
- + len = strlen(edit->buffer + edit->cursor);
- +
- + if (len > 0) {
- + Field_Kill_Text(edit, edit->cursor, edit->cursor + len - 1);
- + }
- +}
- +
- +/*
- +==================
- +Field_Backward_Kill_Line
- +
- +This is called unix-line-discard in GNU Readline.
- +It kills from the start of the line until the current position (moving everything backwards).
- +
- +Example from bash (GNU Readline):
- +
- + v---------------- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------------------------- cursor
- +modi$ 11/xorg.conf
- +
- + v---- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------------------------- cursor
- +modi$
- +==================
- +*/
- +static void Field_Backward_Kill_Line( field_t *edit ) {
- + Add_Kill_Ring_Entry(edit->buffer, 0, edit->cursor - 1);
- +
- + memmove(edit->buffer, edit->buffer + edit->cursor, MAX_EDIT_LINE - edit->cursor);
- + memset(edit->buffer + MAX_EDIT_LINE - edit->cursor, 0, MAX_EDIT_LINE - (MAX_EDIT_LINE - edit->cursor));
- +
- + edit->cursor = 0;
- + edit->scroll = 0;
- +}
- +
- +/*
- +==================
- +Field_Backward_Word
- +
- +Emacs defines a word to be a letter/digit but I think that's confusing to
- +non-Emacs users so I'm using space/non-space.
- +
- +This doesn't match GNU Readline so this shows how it should work
- +
- +If the cursor is on a space, it moves to the beginning of the first word behind it.
- +Otherwise, it positions the cursor at the beginning of the current word.
- +
- +Example:
- +
- + v------------------ cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------------------------ cursor
- +modi$ ls /etc/X11/xorg.conf
- +
- +
- +This shows how it will skip the current word if it's on the first character of it already.
- +It would behave the same way if the cursor was on top of whitespace.
- +
- + v-------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v------------------------ cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +
- +
- + v-- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v-------------------- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +
- +
- + v--------------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v--------------------------- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +==================
- +*/
- +static void Field_Backward_Word( field_t *edit) {
- + int index;
- + int saw_char = 0;
- +
- + if (edit->cursor <= 0) {
- + return;
- + }
- +
- + for (index = edit->cursor - 1; index > 0; index--) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_char) {
- + // The last char was the end of a word. Go back.
- + index++;
- + break;
- + }
- + } else {
- + saw_char = 1;
- + }
- + }
- +
- + edit->cursor = index;
- +}
- +
- +/*
- +==================
- +Field_Forward_Word
- +
- +Emacs defines a word to be a letter/digit but I think that's confusing to
- +non-Emacs users so I'm using space/non-space.
- +
- +This doesn't match GNU Readline so this shows how it should work
- +
- +If the cursor is on a space, it moves to the beginning of the next word.
- +Otherwise, it positions the cursor after the end of the current word.
- +
- +Example:
- +
- +When it is on the last word, it will advance to the end of it.
- +
- + v------------------ cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- + v------- cursor
- +orig$ ls /etc/X11/xorg.conf
- +
- +
- +This shows how it will skip the current word if it's on the first character of it already.
- +It would behave the same way if the cursor was on top of whitespace.
- +
- + v----------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v--------------------- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +
- +
- +This shows how it will skip the current word if it's on the first character of it already.
- +It would behave the same way if the cursor was on top of whitespace.
- +
- + v---------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v-------------------- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +==================
- +*/
- +static void Field_Forward_Word( field_t *edit ) {
- + int index;
- + int saw_space = 0;
- + int len = strlen( edit->buffer );
- +
- + if (edit->cursor >= len - 1) {
- + return;
- + }
- +
- + for (index = edit->cursor + 1; index < len - 1; index++) {
- + if (isspace(edit->buffer[index])) {
- + saw_space = 1;
- +
- + } else {
- + if (saw_space) {
- + break;
- + }
- + }
- + }
- +
- + edit->cursor = index;
- +}
- +
- +/*
- +==================
- +Field_Uppercase_Word
- +
- +If the cursor is on a space, it moves to the beginning of the first word ahead.
- +Otherwise, it positions the cursor at the beginning of the current word.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v-- cursor
- +modi$ ls -la /etc/X11/xorg.CONF
- +
- + v--------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v-- cursor
- +modi$ ls -la /ETC/X11/XORG.CONF
- +==================
- +*/
- +static void Field_Uppercase_Word( field_t *edit ) {
- + int index;
- + int saw_nonspace = 0;
- + int len = strlen( edit->buffer );
- +
- + if (edit->cursor >= len - 1) {
- + return;
- + }
- +
- + for (index = edit->cursor; index < len; index++) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_nonspace) {
- + break;
- + }
- + } else {
- + edit->buffer[index] = (char)toupper((unsigned char)edit->buffer[index]);
- + saw_nonspace = 1;
- + }
- + }
- +
- + edit->cursor = index;
- +}
- +
- +/*
- +==================
- +Field_Lowercase_Word
- +
- +If the cursor is on a space, it moves to the beginning of the first word behind it.
- +Otherwise, it positions the cursor at the beginning of the current word.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.CONF
- +
- + v-- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +
- + v--------------------- cursor
- +orig$ ls -la /ETC/X11/XORG.CONF
- +
- + v-- cursor
- +modi$ ls -la /etc/x11/xorg.conf
- +==================
- +*/
- +static void Field_Lowercase_Word( field_t *edit ) {
- + int index;
- + int saw_nonspace = 0;
- + int len = strlen( edit->buffer );
- +
- + if (edit->cursor >= len - 1) {
- + return;
- + }
- +
- + for (index = edit->cursor; index < len; index++) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_nonspace) {
- + break;
- + }
- +
- + } else {
- + edit->buffer[index] = (char)tolower((unsigned char)edit->buffer[index]);
- + saw_nonspace = 1;
- + }
- + }
- +
- + edit->cursor = index;
- +}
- +
- +/*
- +==================
- +Field_Capitalize_Word
- +
- +If the cursor is on a space, it moves to the beginning of the first word behind it.
- +Otherwise, it positions the cursor at the beginning of the current word.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.CONF
- +
- + v-- cursor
- +modi$ ls -la /etc/X11/xorg.Conf
- +
- + v------------------ cursor
- +orig$ ls -la /ETC/X11/XORG.CONF
- +
- + v-- cursor
- +modi$ ls -la /ETc/x11/xorg.conf
- +==================
- +*/
- +static void Field_Capitalize_Word( field_t *edit ) {
- + int index;
- + int saw_nonspace = 0;
- + int len = strlen( edit->buffer );
- +
- + if (edit->cursor >= len - 1) {
- + return;
- + }
- +
- + for (index = edit->cursor; index < len; index++) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_nonspace) {
- + break;
- + }
- +
- + } else {
- + if (saw_nonspace == 0) {
- + edit->buffer[index] = (char)toupper((unsigned char)edit->buffer[index]);
- + } else {
- + edit->buffer[index] = (char)tolower((unsigned char)edit->buffer[index]);
- + }
- + saw_nonspace = 1;
- + }
- + }
- +
- + edit->cursor = index;
- +}
- +
- +/*
- +==================
- +Field_Backward_Kill_Word
- +
- +Emacs defines a word to be a letter/digit but I think that's confusing to
- +non-Emacs users so I'm using space/non-space.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.CONF
- +
- + v-------------------- cursor
- +modi$ ls -la CONF
- +
- + v------------------ cursor
- +orig$ ls -la /E
- +
- + v-------------------- cursor
- +modi$ ls -la TC/X11/XORG.CONF
- +==================
- +*/
- +static void Field_Backward_Kill_Word( field_t *edit) {
- + int saw_nonspace = 0;
- + int previous_index = edit->cursor;
- + int index = 0;
- +
- + if (edit->cursor <= 0) {
- + return;
- + }
- +
- + for (index = edit->cursor - 1; index > 0; index--) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_nonspace) {
- + index++;
- + break;
- + }
- + } else {
- + saw_nonspace = 1;
- + }
- + }
- +
- + Field_Kill_Text(edit, index, previous_index);
- +}
- +
- +/*
- +==================
- +Field_Kill_Word
- +
- +Emacs defines a word to be a letter/digit but I think that's confusing to
- +non-Emacs users so I'm using space/non-space.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.CONF
- +
- + v------ cursor
- +modi$ ls -la /etc/X11/xorg.
- +
- + v------------------ cursor
- +orig$ ls -la /ETC/X11/XORG.CONF
- +
- + v------------------ cursor
- +modi$ ls -la /E
- +==================
- +*/
- +static void Field_Kill_Word( field_t *edit ) {
- + int saw_nonspace = 0;
- + int previous_index = edit->cursor;
- + int index;
- + int len = strlen( edit->buffer );
- +
- + if (edit->cursor >= len - 1) {
- + return;
- + }
- +
- + for (index = edit->cursor; index < len; index++) {
- + if (isspace(edit->buffer[index])) {
- + if (saw_nonspace) {
- + index--;
- + break;
- + }
- + } else {
- + saw_nonspace = 1;
- + }
- + }
- +
- + Field_Kill_Text(edit, previous_index, index);
- +}
- +
- +/*
- +==================
- +Field_Kill_Word
- +
- +Emacs defines a word to be a letter/digit but I think that's confusing to
- +non-Emacs users so I'm using space/non-space.
- +
- + v------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v------ cursor
- +modi$ ls -la /etc/X11/xorgc.onf
- +
- + v--------------------------- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v--------------------------- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +
- + v---- cursor
- +orig$ ls -la /etc/X11/xorg.conf
- +
- + v--- cursor
- +modi$ ls -la /etc/X11/xorg.cofn
- +
- + v---- cursor
- +orig$ ls -la /etc/X11/xorg.cofn
- +
- + v--- cursor
- +modi$ ls -la /etc/X11/xorg.conf
- +==================
- +*/
- +static void Field_Transpose_Chars( field_t *edit ) {
- + int len;
- + char cache_val;
- +
- + if ( edit->cursor <= 0 ) {
- + return;
- + }
- +
- + // If we're at the end of the line, pretend that we're on the 2nd to last.
- + len = strlen( edit->buffer );
- + if (edit->cursor == len) {
- + edit->cursor--;
- + if ( edit->cursor < edit->scroll )
- + {
- + edit->scroll--;
- + }
- + }
- +
- + cache_val = edit->buffer[edit->cursor - 1];
- + edit->buffer[edit->cursor - 1] = edit->buffer[edit->cursor];
- + edit->buffer[edit->cursor] = cache_val;
- +
- + if (edit->cursor < len) {
- + edit->cursor++;
- + }
- + if ( edit->cursor >= edit->widthInChars ) {
- + edit->scroll++;
- + }
- +}
- +
- +/*
- =================
- Field_KeyDownEvent
- @@ -440,21 +1063,36 @@ void Field_KeyDownEvent( field_t *edit, int key ) {
- switch ( key ) {
- case K_DEL:
- - if ( edit->cursor < len ) {
- - memmove( edit->buffer + edit->cursor,
- - edit->buffer + edit->cursor + 1, len - edit->cursor );
- + if (keys[K_CTRL].down) {
- + Field_Backward_Kill_Word( edit );
- +
- + } else {
- + if ( edit->cursor < len ) {
- + memmove( edit->buffer + edit->cursor,
- + edit->buffer + edit->cursor + 1, len - edit->cursor );
- + }
- }
- break;
- case K_RIGHTARROW:
- - if ( edit->cursor < len ) {
- - edit->cursor++;
- + if (keys[K_CTRL].down) {
- + Field_Forward_Word(edit);
- +
- + } else {
- + if ( edit->cursor < len ) {
- + edit->cursor++;
- + }
- }
- break;
- case K_LEFTARROW:
- - if ( edit->cursor > 0 ) {
- - edit->cursor--;
- + if (keys[K_CTRL].down) {
- + Field_Backward_Word(edit);
- +
- + } else {
- + if ( edit->cursor > 0 ) {
- + edit->cursor--;
- + }
- }
- break;
- @@ -490,18 +1128,57 @@ Field_CharEvent
- void Field_CharEvent( field_t *edit, int ch ) {
- int len;
- - if ( ch == 'v' - 'a' + 1 ) { // ctrl-v is paste
- + if ( ch == 'v' - 'a' + 1 ) { // ctrl-v is clipboard paste
- Field_Paste( edit );
- return;
- }
- + if ( ch == 'y' - 'a' + 1 ) { // ctrl-y is yank (kill ring)
- + Use_Kill_Ring_Entry( edit );
- + return;
- + }
- +
- if ( ch == 'c' - 'a' + 1 ) { // ctrl-c clears the field
- Field_Clear( edit );
- return;
- }
- + // kill goes from the current position to the end of the line
- + // Unlike Emacs/Readline, this does not add it to the kill region (yet).
- + if ( ch == 'k' - 'a' + 1 ) { // ctrl-k clears from here to EOL
- + Field_Kill_Line( edit );
- + return;
- + }
- +
- + if ( ch == 'u' - 'a' + 1 ) {
- + Field_Backward_Kill_Line( edit );
- + return;
- + }
- +
- len = strlen( edit->buffer );
- + if ( ch == 'd' - 'a' + 1 ) { // ctrl+d is delete
- + if ( edit->cursor < len ) {
- + memmove( edit->buffer + edit->cursor,
- + edit->buffer + edit->cursor + 1, len - edit->cursor );
- + }
- + return;
- + }
- +
- + if ( ch == 'f' - 'a' + 1 ) { // ctrl-f is move forward 1 char
- + if ( edit->cursor < len ) {
- + edit->cursor++;
- + }
- + return;
- + }
- +
- + if ( ch == 'b' - 'a' + 1 ) { // ctrl-b is move backwards 1 char
- + if ( edit->cursor > 0 ) {
- + edit->cursor--;
- + }
- + return;
- + }
- +
- if ( ch == 'h' - 'a' + 1 ) { // ctrl-h is backspace
- if ( edit->cursor > 0 ) {
- memmove( edit->buffer + edit->cursor - 1,
- @@ -515,6 +1192,14 @@ void Field_CharEvent( field_t *edit, int ch ) {
- return;
- }
- + // This handles the transpose similar to GNU Readline and not GNU Emacs.
- + // At the beginning of the line, it does nothing. At the end of the line,
- + // it will transpose the last 2 chars without moving the cursor.
- + if ( ch == 't' - 'a' + 1 ) { // ctrl-t is transpose chars
- + Field_Transpose_Chars( edit );
- + return;
- + }
- +
- if ( ch == 'a' - 'a' + 1 ) { // ctrl-a is home
- edit->cursor = 0;
- edit->scroll = 0;
- @@ -527,6 +1212,65 @@ void Field_CharEvent( field_t *edit, int ch ) {
- return;
- }
- + if ( ch == 'w' - 'a' + 1 ) {
- + Field_Backward_Kill_Word( edit );
- + return;
- + }
- +
- + // Treat ALT as Meta
- + if (keys[K_ALT].down) {
- + int found = 1;
- +
- + switch (ch) {
- + case 'f':
- + Field_Forward_Word( edit );
- + break;
- +
- + case 'b':
- + Field_Backward_Word( edit );
- + break;
- +
- + case 'd':
- + Field_Kill_Word( edit );
- + break;
- +
- + case 'u':
- + /* uppercase-word */
- + Field_Uppercase_Word( edit );
- + break;
- +
- + case 'l':
- + /* downcase-word */
- + Field_Lowercase_Word( edit );
- + break;
- +
- + case 'c':
- + /* capitalize word */
- + Field_Capitalize_Word( edit );
- + break;
- +
- + case 'y':
- + /* rotate then yank */
- + /* There's only one buffer currently so this isn't implemented */
- + break;
- +
- + default:
- + found = 0;
- + }
- +
- + if (found) {
- + if ( edit->cursor >= edit->widthInChars ) {
- + edit->scroll++;
- + }
- +
- + if ( edit->cursor == len + 1) {
- + edit->buffer[edit->cursor] = 0;
- + }
- +
- + return;
- + }
- + }
- +
- //
- // ignore any other non printable chars
- //
- @@ -634,6 +1378,8 @@ void Console_Key (int key) {
- return;
- }
- + // XXX Need M-< and M-> for first and last history, respectively
- +
- // command history (ctrl-p ctrl-n for unix style)
- if ( (key == K_MWHEELUP && keys[K_SHIFT].down) || ( key == K_UPARROW ) || ( key == K_KP_UPARROW ) ||
- diff --git a/code/client/keys.h b/code/client/keys.h
- index 0168468..4479736 100644
- --- a/code/client/keys.h
- +++ b/code/client/keys.h
- @@ -39,6 +39,9 @@ void Field_BigDraw( field_t *edit, int x, int y, int width, qboolean showCursor,
- #define COMMAND_HISTORY 32
- extern field_t historyEditLines[COMMAND_HISTORY];
- +// Only 1 for now
- +extern killring_t killRing;
- +
- extern field_t g_consoleField;
- extern field_t chatField;
- extern int anykeydown;
- diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c
- index 550d100..2809e6b 100644
- --- a/code/qcommon/q_shared.c
- +++ b/code/qcommon/q_shared.c
- @@ -683,24 +683,88 @@ int Q_isalpha( int c )
- return ( 0 );
- }
- -char* Q_strrchr( const char* string, int c )
- +/* $OpenBSD: index.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
- +/*-
- + * Copyright (c) 1990 The Regents of the University of California.
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +char *
- +Q_strchr(const char *p, int ch)
- {
- - char cc = c;
- - char *s;
- - char *sp=(char *)0;
- -
- - s = (char*)string;
- + for (;; ++p) {
- + if (*p == ch)
- + return((char *)p);
- + if (!*p)
- + return((char *)NULL);
- + }
- + /* NOTREACHED */
- +}
- - while (*s)
- - {
- - if (*s == cc)
- - sp = s;
- - s++;
- - }
- - if (cc == 0)
- - sp = s;
- +/* $OpenBSD: rindex.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
- +/*
- + * Copyright (c) 1988 Regents of the University of California.
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +char *
- +Q_strrchr(const char *p, int ch)
- +{
- + char *save;
- - return sp;
- + for (save = NULL;; ++p) {
- + if (*p == ch)
- + save = (char *)p;
- + if (!*p)
- + return(save);
- + }
- + /* NOTREACHED */
- }
- qboolean Q_isanumber( const char *s )
- @@ -730,13 +794,13 @@ qboolean Q_isintegral( float f )
- =============
- Q_strncpyz
- -Safe strncpy that ensures a trailing zero
- +Safe strncpy that ensures a trailing zero. This now uses Q_strlcpy().
- =============
- */
- void Q_strncpyz( char *dest, const char *src, int destsize ) {
- - if ( !dest ) {
- - Com_Error( ERR_FATAL, "Q_strncpyz: NULL dest" );
- - }
- + if ( !dest ) {
- + Com_Error( ERR_FATAL, "Q_strncpyz: NULL dest" );
- + }
- if ( !src ) {
- Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" );
- }
- @@ -744,8 +808,9 @@ void Q_strncpyz( char *dest, const char *src, int destsize ) {
- Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" );
- }
- - strncpy( dest, src, destsize-1 );
- - dest[destsize-1] = 0;
- + if (Q_strlcpy(dest, src, destsize) >= destsize) {
- + // XXX Handle truncation?
- + }
- }
- int Q_stricmpn (const char *s1, const char *s2, int n) {
- @@ -758,8 +823,7 @@ int Q_stricmpn (const char *s1, const char *s2, int n) {
- return -1;
- }
- else if ( s2==NULL )
- - return 1;
- -
- + return 1;
- do {
- @@ -786,6 +850,7 @@ int Q_stricmpn (const char *s1, const char *s2, int n) {
- return 0; // strings are equal
- }
- +
- int Q_strncmp (const char *s1, const char *s2, int n) {
- int c1, c2;
- @@ -805,8 +870,9 @@ int Q_strncmp (const char *s1, const char *s2, int n) {
- return 0; // strings are equal
- }
- +// This now uses the OpenBSD version
- int Q_stricmp (const char *s1, const char *s2) {
- - return (s1 && s2) ? Q_stricmpn (s1, s2, 99999) : -1;
- + return (s1 && s2) ? Q_stricmpn(s1, s2, 99999) : -1;
- }
- @@ -832,50 +898,225 @@ char *Q_strupr( char *s1 ) {
- return s1;
- }
- +/* $OpenBSD: strcasestr.c,v 1.3 2006/03/31 05:34:55 deraadt Exp $ */
- +/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
- +/*-
- + * Copyright (c) 1990, 1993
- + * The Regents of the University of California. All rights reserved.
- + *
- + * This code is derived from software contributed to Berkeley by
- + * Chris Torek.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +/*
- + * Find the first occurrence of find in s, ignore case.
- + */
- +char *
- +Q_strcasestr(const char *s, const char *find)
- +{
- + char c, sc;
- + size_t len;
- +
- + if ((c = *find++) != 0) {
- + c = (char)tolower((unsigned char)c);
- + len = strlen(find);
- + do {
- + do {
- + if ((sc = *s++) == 0)
- + return (NULL);
- + } while ((char)tolower((unsigned char)sc) != c);
- + } while (Q_stricmpn(s, find, len) != 0);
- + s--;
- + }
- + return ((char *)s);
- +}
- +
- +/* Alias for existing code */
- +const char *
- +Q_stristr(const char *s, const char *find)
- +{
- + return Q_strcasestr(s, find);
- +}
- +
- +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
- +/*
- + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- + *
- + * Permission to use, copy, modify, and distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +/*
- + * Appends src to string dst of size siz (unlike strncat, siz is the
- + * full size of dst, not space left). At most siz-1 characters
- + * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
- + * Returns strlen(src) + MIN(siz, strlen(initial dst)).
- + * If retval >= siz, truncation occurred.
- + */
- +size_t
- +Q_strlcat(char *dst, const char *src, size_t siz)
- +{
- + char *d = dst;
- + const char *s = src;
- + size_t n = siz;
- + size_t dlen;
- +
- + if (! dst) {
- + Com_Error( ERR_FATAL, "Q_strlcat: NULL dest" );
- + }
- + if ( !src ) {
- + Com_Error( ERR_FATAL, "Q_strlcat: NULL src" );
- + }
- + if ( siz < 1) {
- + Com_Error(ERR_FATAL, "Q_strlcat: siz < 1" );
- + }
- +
- + /* Find the end of dst and adjust bytes left but don't go past end */
- + while (n-- != 0 && *d != '\0')
- + d++;
- + dlen = d - dst;
- + n = siz - dlen;
- +
- + if (n == 0)
- + return(dlen + strlen(s));
- + while (*s != '\0') {
- + if (n != 1) {
- + *d++ = *s;
- + n--;
- + }
- + s++;
- + }
- + *d = '\0';
- -// never goes past bounds or leaves without a terminating 0
- -void Q_strcat( char *dest, int size, const char *src ) {
- - int l1;
- + return(dlen + (s - src)); /* count does not include NUL */
- +}
- - l1 = strlen( dest );
- - if ( l1 >= size ) {
- +/* For legacy code, provide the Q_strcat interface to Q_strlcat() */
- +void Q_strcat(char *dst, int siz, const char *src)
- +{
- + size_t l1 = strlen( dst );
- + if ( l1 >= siz ) {
- Com_Error( ERR_FATAL, "Q_strcat: already overflowed" );
- }
- - Q_strncpyz( dest + l1, src, size - l1 );
- +
- + Q_strlcat(dst, src, siz);
- }
- +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
- /*
- -* Find the first occurrence of find in s.
- -*/
- -const char *Q_stristr( const char *s, const char *find)
- + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- + *
- + * Permission to use, copy, modify, and distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +/*
- + * Copy src to string dst of size siz. At most siz-1 characters
- + * will be copied. Always NUL terminates (unless siz == 0).
- + * Returns strlen(src); if retval >= siz, truncation occurred.
- + */
- +size_t
- +Q_strlcpy(char *dst, const char *src, size_t siz)
- {
- - char c, sc;
- - size_t len;
- -
- - if ((c = *find++) != 0)
- - {
- - if (c >= 'a' && c <= 'z')
- - {
- - c -= ('a' - 'A');
- - }
- - len = strlen(find);
- - do
- - {
- - do
- - {
- - if ((sc = *s++) == 0)
- - return NULL;
- - if (sc >= 'a' && sc <= 'z')
- - {
- - sc -= ('a' - 'A');
- - }
- - } while (sc != c);
- - } while (Q_stricmpn(s, find, len) != 0);
- - s--;
- - }
- - return s;
- + char *d = dst;
- + const char *s = src;
- + size_t n = siz;
- +
- + // Mimic the error cheking from the previous Q_strcpynz
- + if (! dst) {
- + Com_Error( ERR_FATAL, "Q_strlcpy: NULL dest" );
- + }
- + if ( !src ) {
- + Com_Error( ERR_FATAL, "Q_strlcpy: NULL src" );
- + }
- + if ( siz < 1) {
- + Com_Error(ERR_FATAL, "Q_strlcpy: siz < 1" );
- + }
- +
- + /* Copy as many bytes as will fit */
- + if (n != 0) {
- + while (--n != 0) {
- + if ((*d++ = *s++) == '\0')
- + break;
- + }
- + }
- +
- + /* Not enough room in dst, add NUL and traverse rest of src */
- + if (n == 0) {
- + if (siz != 0)
- + *d = '\0'; /* NUL-terminate dst */
- + while (*s++)
- + ;
- + }
- +
- + return(s - src - 1); /* count does not include NUL */
- }
- +/* $OpenBSD: strnlen.c,v 1.3 2010/06/02 12:58:12 millert Exp $ */
- +/*
- + * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
- + *
- + * Permission to use, copy, modify, and distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +size_t
- +Q_strnlen(const char *str, size_t maxlen)
- +{
- + const char *cp;
- +
- + for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
- + ;
- +
- + return (size_t)(cp - str);
- +}
- int Q_PrintStrlen( const char *string ) {
- int len;
- diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h
- index 6942a62..7c9274c 100644
- --- a/code/qcommon/q_shared.h
- +++ b/code/qcommon/q_shared.h
- @@ -26,6 +26,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- // q_shared.h -- included first by ALL program modules.
- // A user mod should never modify this file
- +/* extern __inline is a GNU C extension */
- +#ifdef __GNUC__
- +# if defined(__GNUC_STDC_INLINE__)
- +# define __CTYPE_INLINE extern __inline __attribute__((__gnu_inline__))
- +# else
- +# define __CTYPE_INLINE extern __inline
- +# endif
- +#else
- +# define __CTYPE_INLINE
- +#endif
- +
- #ifdef STANDALONE
- #define PRODUCT_NAME "iofoo3"
- #define BASEGAME "foobar"
- @@ -701,6 +712,7 @@ int Q_isprint( int c );
- int Q_islower( int c );
- int Q_isupper( int c );
- int Q_isalpha( int c );
- +
- qboolean Q_isanumber( const char *s );
- qboolean Q_isintegral( float f );
- @@ -710,13 +722,21 @@ int Q_strncmp (const char *s1, const char *s2, int n);
- int Q_stricmpn (const char *s1, const char *s2, int n);
- char *Q_strlwr( char *s1 );
- char *Q_strupr( char *s1 );
- -char *Q_strrchr( const char* string, int c );
- const char *Q_stristr( const char *s, const char *find);
- -// buffer size safe library replacements
- +// buffer size safe library replacements (uses strlcpy and strlcat)
- void Q_strncpyz( char *dest, const char *src, int destsize );
- void Q_strcat( char *dest, int size, const char *src );
- +// OpenBSD implementations
- +char *Q_strchr(const char *p, int ch);
- +char *Q_strrchr(const char *p, int ch);
- +char *Q_strcasestr(const char *s, const char *find);
- +int Q_strncasecmp(const char *s1, const char *s2, size_t n);
- +size_t Q_strnlen(const char *str, size_t maxlen);
- +size_t Q_strlcat(char *dst, const char *src, size_t siz);
- +size_t Q_strlcpy(char *dst, const char *src, size_t siz);
- +
- // strlen that discounts Quake color sequences
- int Q_PrintStrlen( const char *string );
- // removes color sequences from string
- @@ -1298,5 +1318,4 @@ typedef enum _flag_status {
- #define CDKEY_LEN 16
- #define CDCHKSUM_LEN 2
- -
- #endif // __Q_SHARED_H
- diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
- index c6a61e2..7e409f9 100644
- --- a/code/qcommon/qcommon.h
- +++ b/code/qcommon/qcommon.h
- @@ -729,6 +729,11 @@ typedef struct {
- char buffer[MAX_EDIT_LINE];
- } field_t;
- +typedef struct {
- + int length;
- + char buffer[MAX_EDIT_LINE];
- +} killring_t;
- +
- void Field_Clear( field_t *edit );
- void Field_AutoComplete( field_t *edit );
- void Field_CompleteKeyname( void );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement