aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-11-18 22:41:52 +0100
committerRaymaekers Luca <raymaekers.luca@gmail.com>2024-11-18 22:42:42 +0100
commitce8790254a32ebc77a39ebd80dd1ee0f0a8be3cb (patch)
treeaca67f175bd770d64f7d67a0dd7245929708370a
parent0d635bc20467b3d789091f14affe8c499c74d2ea (diff)
Added pasting clipboard on ctrl-y
-rw-r--r--README.md2
-rw-r--r--archived.md2
-rw-r--r--chatty.c110
-rw-r--r--ui.c2
4 files changed, 103 insertions, 13 deletions
diff --git a/README.md b/README.md
index 1541f41..cb485bb 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,6 @@ The idea is the following:
- [ ] bug: when connecting two clients of the same account
- [ ] bug: wrapping does not work and displays nothing if there is no screen space
- [ ] bug: reconnect does not work when server does not know id
-- [ ] markup for messages
- [ ] convert tabs to spaces
## server
@@ -43,6 +42,7 @@ The idea is the following:
- `Ctrl+C` | `Ctrl+D`: quits
- `Ctrl+U`: Erase input line
- `Ctrl+W`: Erase word behind cursor
+- `Ctrl+Y`: Paste clipboard into input field
## Resources I used for building this
- source code I looked at:
diff --git a/archived.md b/archived.md
index 7895224..afebf8b 100644
--- a/archived.md
+++ b/archived.md
@@ -11,6 +11,8 @@
- [x] bug: when reconnecting nrecv != -1
- [x] bug: when disconnecting
- [x] use error type success to say that authentication succeeded
+- [x] markup for messages
+- [x] clipboard shortcut
## Server
- [x] import clients
diff --git a/chatty.c b/chatty.c
index c827448..233e8b3 100644
--- a/chatty.c
+++ b/chatty.c
@@ -1,16 +1,13 @@
#define TB_IMPL
#include "termbox2.h"
-#include "chatty.h"
-#include "protocol.h"
-#include "ui.c"
-
#include <arpa/inet.h>
#include <assert.h>
#include <locale.h>
#include <poll.h>
#include <pthread.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#define TIMEOUT_POLL 60 * 1000
// time to reconnect in seconds
@@ -23,6 +20,12 @@
// enable logging
#define LOGGING
+#define DEBUG
+
+#include "chatty.h"
+#include "protocol.h"
+#include "ui.c"
+
enum { FDS_BI = 0, // for one-way communication with the server (eg. TextMessage)
FDS_UNI, // For two-way communication with the server (eg. IDMessage)
FDS_TTY,
@@ -36,6 +39,11 @@ typedef struct {
#define USER_FMT "[%s](%lu)"
#define USER_ARG(client) client.Author, client.ID
+typedef struct {
+ s32 NumRead;
+ u32 Error;
+} command_output;
+
// User used by chatty
global_variable User user = {0};
// Address of chatty server
@@ -51,11 +59,11 @@ fillstr(u32* Str, u32 ch, u32 Len)
// Centered popup displaying message in the appropriate cololrs
void
-popup(u32 fg, u32 bg, char* text)
+popup(u32 fg, u32 bg, u8* text)
{
- u32 len = strlen(text);
+ u32 len = strlen((char*)text);
assert(len > 0);
- tb_print(global.width / 2 - len / 2, global.height / 2, fg, bg, text);
+ tb_print(global.width / 2 - len / 2, global.height / 2, fg, bg, (char*)text);
}
// Returns client in clientsArena matching id
@@ -213,6 +221,56 @@ thread_reconnect(void* fds_ptr)
return 0;
}
+command_output
+run_command_get_output(char *Command, char *Argv[], u8 *OutputBuffer, int Len)
+{
+ command_output Result = {0};
+
+ int CommandPipe[2];
+ int Error = pipe(CommandPipe);
+ assert(Error != -1);
+
+ int Pid = fork();
+ assert(Pid != -1);
+
+ // Run command in child
+ if (!Pid)
+ {
+ dup2(CommandPipe[1], STDOUT_FILENO); //redirect stdout to Pipe
+ close(CommandPipe[0]);
+ close(CommandPipe[1]);
+
+ int fd = open("/dev/null", O_WRONLY);
+ dup2(fd, STDERR_FILENO);
+
+ execvp(Command, Argv);
+ }
+
+ // Wait for child
+ int statval;
+ waitpid(Pid, &statval, 0);
+
+ if(WIFEXITED(statval))
+ {
+ int ExitCode = WEXITSTATUS(statval);
+ if (ExitCode)
+ {
+ Result.Error = ExitCode;
+ }
+ }
+ else
+ {
+ Result.Error = 1;
+ return Result;
+ }
+
+ close(CommandPipe[1]);
+
+ Result.NumRead = read(CommandPipe[0], OutputBuffer, Len);
+ assert(Result.NumRead != -1);
+
+ return Result;
+}
// home screen, the first screen the user sees
// it displays a prompt with the user input of input_len wide characters
// and the received messages from msgsArena
@@ -250,7 +308,7 @@ screen_home(Arena* ScratchArena,
// 03:24:33 [TlasT] │ I am fine
// 03:24:33 [Fin] │ I am too
{
- u32 VerticalBarOffset = TIMESTAMP_LEN + AUTHOR_LEN + 2;
+ s32 VerticalBarOffset = TIMESTAMP_LEN + AUTHOR_LEN + 2;
u32 FreeHeight = global.height - box_height;
if (FreeHeight <= 0)
@@ -333,7 +391,7 @@ screen_home(Arena* ScratchArena,
tb_printf(TIMESTAMP_LEN, MessageY, fg, 0, "[%s]", client->Author);
// Only display when there is enough space
- if (global.width > VerticalBarOffset + 2)
+ if (global.width > VerticalBarOffset + 2)
{
raw_result RawText = markdown_to_raw(ScratchArena, (u32*)&message->text, message->len);
markdown_formatoptions MDFormat = preprocess_markdown(ScratchArena,
@@ -460,7 +518,7 @@ screen_home(Arena* ScratchArena,
if (fds[FDS_UNI].fd == -1 || fds[FDS_BI].fd == -1)
{
// show error popup
- popup(TB_RED, TB_BLACK, "Server disconnected.");
+ popup(TB_RED, TB_BLACK, (u8*)"Server disconnected.");
}
}
}
@@ -670,7 +728,39 @@ main(int argc, char** argv)
kill(pid, SIGSTOP);
tb_init();
} break;
+ case TB_KEY_CTRL_Y: // Paste clipboard contents to input
+ {
+ u32 OutputBufferLen = INPUT_LIMIT - InputLen;
+ if (OutputBufferLen <= 0) break;
+ u8 OutputBuffer[OutputBufferLen];
+
+ char *PathName = "xclip";
+ char *Argv[] = {PathName, "-o", "-sel", "c", 0};
+
+ command_output Output = run_command_get_output(PathName, Argv, OutputBuffer, OutputBufferLen - 1);
+ if (Output.Error) break;
+
+ // Remove trailing whitespace
+ int BufferIndex = Output.NumRead - 1;
+ while (BufferIndex > 0 &&
+ (OutputBuffer[BufferIndex] == '\n' ||
+ OutputBuffer[BufferIndex] == '\t'))
+ {
+ OutputBuffer[BufferIndex] = 0;
+ BufferIndex--;
+ }
+
+ // Append to output
+ for (s32 BufferIndex = 0; BufferIndex < Output.NumRead; BufferIndex++)
+ {
+ // convert u8 to u32
+ u32 ch = OutputBuffer[BufferIndex];
+ Input[InputLen] = ch;
+ InputLen++;
+ }
+
+ } break;
case TB_KEY_CTRL_D:
case TB_KEY_CTRL_C:
quit = 1;
diff --git a/ui.c b/ui.c
index 9148810..ed2aa24 100644
--- a/ui.c
+++ b/ui.c
@@ -1,5 +1,3 @@
-#define DEBUG
-
// Format option at a position in raw text, used when iterating to know when to toggle a color
// option.
typedef struct {