diff --git a/CommandScreen.c b/CommandScreen.c index a61b14709..c7b42b986 100644 --- a/CommandScreen.c +++ b/CommandScreen.c @@ -14,6 +14,8 @@ in the source distribution for its full text. #include #include +#include "CRT.h" +#include "FunctionBar.h" #include "Macros.h" #include "Panel.h" #include "ProvideCurses.h" @@ -69,18 +71,67 @@ static void CommandScreen_draw(InfoScreen* this) { InfoScreen_drawTitled(this, "Command of process %d - %s", Process_getPid(this->process), Process_getCommand(this->process)); } +static void CommandScreen_copyCommand(const Process* process) { + const char* command = Process_getCommand(process); + if (!command) return; + + char copyCmd[1024]; + bool success = false; + +#ifdef __APPLE__ + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | pbcopy", command); + success = (system(copyCmd) == 0); +#elif defined(__linux__) || defined(__unix__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | xclip -selection clipboard 2>/dev/null", command); + if (system(copyCmd) != 0) { + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | xsel --clipboard 2>/dev/null", command); + success = (system(copyCmd) == 0); + } else { + success = true; + } +#endif + + // Show feedback message + attrset(CRT_colors[FUNCTION_BAR]); + mvhline(LINES - 1, 0, ' ', COLS); + if (success) { + mvaddstr(LINES - 1, 0, "Command copied to clipboard"); + } else { + mvaddstr(LINES - 1, 0, "Copy failed - clipboard not available"); + } + attrset(CRT_colors[DEFAULT_COLOR]); + refresh(); +} + +static bool CommandScreen_onKey(InfoScreen* super, int ch) { + switch (ch) { + case KEY_F(7): + CommandScreen_copyCommand(super->process); + return true; + default: + return false; + } +} + const InfoScreenClass CommandScreen_class = { .super = { .extends = Class(Object), .delete = CommandScreen_delete }, .scan = CommandScreen_scan, - .draw = CommandScreen_draw + .draw = CommandScreen_draw, + .onKey = CommandScreen_onKey }; CommandScreen* CommandScreen_new(Process* process) { CommandScreen* this = AllocThis(CommandScreen); - return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " "); + + static const char* const CommandScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Copy ", "Done ", NULL}; + static const char* const CommandScreenKeys[] = {"F3", "F4", "F5", "F7", "Esc"}; + static const int CommandScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(7), 27}; + + FunctionBar* bar = FunctionBar_new(CommandScreenFunctions, CommandScreenKeys, CommandScreenEvents); + return (CommandScreen*) InfoScreen_init(&this->super, process, bar, LINES - 2, " "); } void CommandScreen_delete(Object* this) { diff --git a/Vector.c b/Vector.c index edb89dfd6..99b63fde9 100644 --- a/Vector.c +++ b/Vector.c @@ -167,6 +167,44 @@ static void insertionSort(Object** array, int left, int right, Object_Compare co } } +static void insertionSortWithContext(Object** array, int left, int right, Object_CompareWithContext compare, void* context) { + for (int i = left + 1; i <= right; i++) { + Object* t = array[i]; + int j = i - 1; + while (j >= left) { + if (compare(array[j], t, context) <= 0) + break; + array[j + 1] = array[j]; + j--; + } + array[j + 1] = t; + } +} + +static int partitionWithContext(Object** array, int left, int right, int pivotIndex, Object_CompareWithContext compare, void* context) { + const Object* pivotValue = array[pivotIndex]; + swap(array, pivotIndex, right); + int storeIndex = left; + for (int i = left; i < right; i++) { + if (compare(array[i], pivotValue, context) <= 0) { + swap(array, i, storeIndex); + storeIndex++; + } + } + swap(array, storeIndex, right); + return storeIndex; +} + +static void quickSortWithContext(Object** array, int left, int right, Object_CompareWithContext compare, void* context) { + if (left >= right) + return; + + int pivotIndex = left + (right - left) / 2; + int pivotNewIndex = partitionWithContext(array, left, right, pivotIndex, compare, context); + quickSortWithContext(array, left, pivotNewIndex - 1, compare, context); + quickSortWithContext(array, pivotNewIndex + 1, right, compare, context); +} + void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare) { assert(compare); assert(Vector_isConsistent(this)); @@ -174,6 +212,19 @@ void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare) { assert(Vector_isConsistent(this)); } +void Vector_sort(Vector* this, Object_CompareWithContext compare, void* context) { + assert(compare); + assert(Vector_isConsistent(this)); + + if (this->items <= 16) { + insertionSortWithContext(this->array, 0, this->items - 1, compare, context); + } else { + quickSortWithContext(this->array, 0, this->items - 1, compare, context); + } + + assert(Vector_isConsistent(this)); +} + void Vector_insertionSort(Vector* this) { assert(this->type->compare); assert(Vector_isConsistent(this)); diff --git a/Vector.h b/Vector.h index 95617eda9..5e451d7ea 100644 --- a/Vector.h +++ b/Vector.h @@ -35,6 +35,10 @@ void Vector_delete(Vector* this); void Vector_prune(Vector* this); +typedef int(*Object_CompareWithContext)(const void*, const void*, void* context); + +void Vector_sort(Vector* this, Object_CompareWithContext compare, void* context); + void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare); static inline void Vector_quickSort(Vector* this) { Vector_quickSortCustomCompare(this, this->type->compare); diff --git a/test_copy_command.c b/test_copy_command.c new file mode 100644 index 000000000..e5c9cf1a3 --- /dev/null +++ b/test_copy_command.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +// Test the copy command logic without htop dependencies +void test_copyCommand(const char* command) { + if (!command) return; + + char copyCmd[1024]; + bool success = false; + + printf("Testing copy for command: %s\n", command); + +#ifdef __APPLE__ + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | pbcopy", command); + printf("macOS command: %s\n", copyCmd); + success = (system(copyCmd) == 0); +#elif defined(__linux__) || defined(__unix__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | xclip -selection clipboard 2>/dev/null", command); + printf("Linux command (xclip): %s\n", copyCmd); + if (system(copyCmd) != 0) { + snprintf(copyCmd, sizeof(copyCmd), "printf '%%s' '%s' | xsel --clipboard 2>/dev/null", command); + printf("Linux command (xsel): %s\n", copyCmd); + success = (system(copyCmd) == 0); + } else { + success = true; + } +#endif + + if (success) { + printf("✅ Command copied to clipboard\n"); + } else { + printf("❌ Copy failed - clipboard not available\n"); + } + printf("\n"); +} + +int main() { + printf("Testing copy command functionality...\n\n"); + + // Test various command types + test_copyCommand("/usr/bin/vim /etc/hosts"); + test_copyCommand("python3 -m http.server 8000"); + test_copyCommand("htop"); + test_copyCommand("ls -la /home/user"); + + return 0; +} \ No newline at end of file