summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml8
-rw-r--r--Action.c8
-rw-r--r--CRT.c1
-rw-r--r--Hashtable.c10
-rw-r--r--OpenFilesScreen.c10
-rw-r--r--Process.c64
-rw-r--r--Process.h24
-rw-r--r--ProcessList.c372
-rw-r--r--ProcessList.h12
-rw-r--r--README5
-rw-r--r--ScreenManager.c8
-rw-r--r--ScreensPanel.c5
-rw-r--r--ScreensPanel.h3
-rw-r--r--Settings.c35
-rw-r--r--Settings.h2
-rw-r--r--TraceScreen.c5
-rw-r--r--XUtils.c36
-rw-r--r--XUtils.h2
-rw-r--r--configure.ac16
-rw-r--r--darwin/DarwinProcess.c46
-rw-r--r--darwin/DarwinProcess.h2
-rw-r--r--darwin/Platform.c6
-rw-r--r--darwin/Platform.h2
-rw-r--r--darwin/PlatformHelpers.h4
-rw-r--r--dragonflybsd/DragonFlyBSDProcess.c4
-rw-r--r--dragonflybsd/DragonFlyBSDProcessList.c1
-rw-r--r--dragonflybsd/Platform.c4
-rw-r--r--dragonflybsd/Platform.h2
-rw-r--r--dragonflybsd/ProcessField.h4
-rw-r--r--freebsd/FreeBSDProcess.c10
-rw-r--r--freebsd/FreeBSDProcess.h1
-rw-r--r--freebsd/FreeBSDProcessList.c3
-rw-r--r--freebsd/Platform.c4
-rw-r--r--freebsd/Platform.h2
-rw-r--r--freebsd/ProcessField.h5
-rw-r--r--htop.1.in16
-rw-r--r--linux/CGroupUtils.c24
-rw-r--r--linux/LinuxProcess.c22
-rw-r--r--linux/LinuxProcessList.c46
-rw-r--r--linux/Platform.c6
-rw-r--r--linux/Platform.h2
-rw-r--r--netbsd/NetBSDProcess.c2
-rw-r--r--netbsd/NetBSDProcessList.c3
-rw-r--r--netbsd/Platform.c6
-rw-r--r--netbsd/Platform.h4
-rw-r--r--openbsd/OpenBSDProcess.c2
-rw-r--r--openbsd/OpenBSDProcessList.c3
-rw-r--r--openbsd/Platform.c4
-rw-r--r--openbsd/Platform.h2
-rw-r--r--pcp-htop.5.in2
-rw-r--r--pcp/PCPProcess.c4
-rw-r--r--pcp/PCPProcessList.c1
-rw-r--r--pcp/Platform.c10
-rw-r--r--pcp/Platform.h6
-rw-r--r--solaris/Platform.c4
-rw-r--r--solaris/Platform.h2
-rw-r--r--solaris/SolarisProcess.c4
-rw-r--r--solaris/SolarisProcessList.c5
-rw-r--r--unsupported/Platform.c2
-rw-r--r--unsupported/UnsupportedProcess.c5
-rw-r--r--unsupported/UnsupportedProcessList.c1
61 files changed, 438 insertions, 476 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 617ed305..af8ed883 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -113,6 +113,10 @@ jobs:
build-ubuntu-latest-pcp:
# Turns out 'ubuntu-latest' can be older than 20.04, we want PCP v5+
runs-on: ubuntu-20.04
+ env:
+ # Until Ubuntu catches up with pcp-5.2.3+:
+ # pcp/Platform.c:309:45: warning: passing argument 2 of ‘pmLookupName’ from incompatible pointer type [-Wincompatible-pointer-types]
+ CFLAGS: -Wno-error=incompatible-pointer-types
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
@@ -120,9 +124,7 @@ jobs:
- name: Bootstrap
run: ./autogen.sh
- name: Configure
- # Until Ubuntu catches up with pcp-5.2.3+, cannot use -werror due to:
- # passing argument 2 of ‘pmLookupName’ from incompatible pointer type
- run: ./configure --enable-pcp --enable-unicode
+ run: ./configure --enable-werror --enable-pcp --enable-unicode
- name: Build
run: make -k
diff --git a/Action.c b/Action.c
index 4e564540..9ee0cdb5 100644
--- a/Action.c
+++ b/Action.c
@@ -189,8 +189,7 @@ static Htop_Reaction actionSetSortColumn(State* st) {
}
Object_delete(sortPanel);
- if (st->pauseProcessUpdate)
- ProcessList_sort(st->pl);
+ st->pl->needsSort = true;
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
@@ -281,8 +280,7 @@ static Htop_Reaction actionLowerPriority(State* st) {
static Htop_Reaction actionInvertSortOrder(State* st) {
ScreenSettings_invertSortOrder(st->settings->ss);
- if (st->pauseProcessUpdate)
- ProcessList_sort(st->pl);
+ st->pl->needsSort = true;
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
@@ -603,7 +601,7 @@ static Htop_Reaction actionHelp(State* st) {
addattrstr(CRT_colors[BAR_BORDER], "[");
addattrstr(CRT_colors[SWAP], "used");
#ifdef HTOP_LINUX
- addattrstr(CRT_colors[BAR_SHADOW], "/");
+ addstr("/");
addattrstr(CRT_colors[SWAP_CACHE], "cache");
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
#else
diff --git a/CRT.c b/CRT.c
index 3a665496..583b6266 100644
--- a/CRT.c
+++ b/CRT.c
@@ -880,6 +880,7 @@ static void CRT_installSignalHandlers(void) {
sigaction (SIGSYS, &act, &old_sig_handler[SIGSYS]);
sigaction (SIGABRT, &act, &old_sig_handler[SIGABRT]);
+ signal(SIGCHLD, SIG_DFL);
signal(SIGINT, CRT_handleSIGTERM);
signal(SIGTERM, CRT_handleSIGTERM);
signal(SIGQUIT, CRT_handleSIGTERM);
diff --git a/Hashtable.c b/Hashtable.c
index c880cf7f..a0cfc9e0 100644
--- a/Hashtable.c
+++ b/Hashtable.c
@@ -90,7 +90,7 @@ size_t Hashtable_count(const Hashtable* this) {
/* https://oeis.org/A014234 */
static const uint64_t OEISprimes[] = {
- 2, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191,
+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191,
16381, 32749, 65521, 131071, 262139, 524287, 1048573,
2097143, 4194301, 8388593, 16777213, 33554393,
67108859, 134217689, 268435399, 536870909, 1073741789,
@@ -191,10 +191,14 @@ void Hashtable_setSize(Hashtable* this, size_t size) {
if (size <= this->items)
return;
+ size_t newSize = nextPrime(size);
+ if (newSize == this->size)
+ return;
+
HashtableItem* oldBuckets = this->buckets;
size_t oldSize = this->size;
- this->size = nextPrime(size);
+ this->size = newSize;
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
this->items = 0;
@@ -282,7 +286,7 @@ void* Hashtable_remove(Hashtable* this, ht_key_t key) {
/* shrink on load-factor < 0.125 */
if (8 * this->items < this->size)
- Hashtable_setSize(this, this->size / 2);
+ Hashtable_setSize(this, this->size / 3); /* account for nextPrime rounding up */
return res;
}
diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c
index 34367ebc..2d191692 100644
--- a/OpenFilesScreen.c
+++ b/OpenFilesScreen.c
@@ -9,6 +9,7 @@ in the source distribution for its full text.
#include "OpenFilesScreen.h"
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
@@ -197,10 +198,11 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
fclose(fd);
int wstatus;
- if (waitpid(child, &wstatus, 0) == -1) {
- pdata->error = 1;
- return pdata;
- }
+ while (waitpid(child, &wstatus, 0) == -1)
+ if (errno != EINTR) {
+ pdata->error = 1;
+ return pdata;
+ }
if (!WIFEXITED(wstatus)) {
pdata->error = 1;
diff --git a/Process.c b/Process.c
index 5214e97a..77e78f04 100644
--- a/Process.c
+++ b/Process.c
@@ -397,7 +397,7 @@ static inline char* stpcpyWithNewlineConversion(char* dstStr, const char* srcStr
* This function makes the merged Command string. It also stores the offsets of the
* basename, comm w.r.t the merged Command string - these offsets will be used by
* Process_writeCommand() for coloring. The merged Command string is also
- * returned by Process_getCommandStr() for searching, sorting and filtering.
+ * returned by Process_getCommand() for searching, sorting and filtering.
*/
void Process_makeCommandStr(Process* this) {
ProcessMergedCommand* mc = &this->mergedCommand;
@@ -417,7 +417,7 @@ void Process_makeCommandStr(Process* this) {
return;
if (this->state == ZOMBIE && !this->mergedCommand.str)
return;
- if (Process_isUserlandThread(this) && settings->showThreadNames && (showThreadNames == mc->prevShowThreadNames))
+ if (Process_isUserlandThread(this) && settings->showThreadNames && (showThreadNames == mc->prevShowThreadNames) && (mc->prevMergeSet == showMergedCommand))
return;
/* this->mergedCommand.str needs updating only if its state or contents changed.
@@ -516,11 +516,14 @@ void Process_makeCommandStr(Process* this) {
assert(cmdlineBasenameStart <= (int)strlen(cmdline));
if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */
- if (showMergedCommand && (!Process_isUserlandThread(this) || showThreadNames) && !procExe && procComm && strlen(procComm)) { /* Prefix column with comm */
+ if ((showMergedCommand || (Process_isUserlandThread(this) && showThreadNames)) && procComm && strlen(procComm)) { /* set column to or prefix it with comm */
if (strncmp(cmdline + cmdlineBasenameStart, procComm, MINIMUM(TASK_COMM_LEN - 1, strlen(procComm))) != 0) {
WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
str = stpcpy(str, procComm);
+ if(!showMergedCommand)
+ return;
+
WRITE_SEPARATOR;
}
}
@@ -729,23 +732,22 @@ void Process_printLeftAlignedField(RichString* str, int attr, const char* conten
RichString_appendChr(str, attr, ' ', width + 1 - columns);
}
-void Process_printPercentage(float val, char* buffer, int n, int* attr) {
+void Process_printPercentage(float val, char* buffer, int n, uint8_t width, int* attr) {
if (val >= 0) {
if (val < 99.9F) {
if (val < 0.05F) {
*attr = CRT_colors[PROCESS_SHADOW];
}
- xSnprintf(buffer, n, "%4.1f ", val);
- } else if (val < 999) {
- *attr = CRT_colors[PROCESS_MEGABYTES];
- xSnprintf(buffer, n, "%3d. ", (int)val);
+ xSnprintf(buffer, n, "%*.1f ", width, val);
} else {
*attr = CRT_colors[PROCESS_MEGABYTES];
- xSnprintf(buffer, n, "%4d ", (int)val);
+ if (val < 100.0F)
+ val = 100.0F; // Don't round down and display "val" as "99".
+ xSnprintf(buffer, n, "%*.0f ", width, val);
}
} else {
*attr = CRT_colors[PROCESS_SHADOW];
- xSnprintf(buffer, n, " N/A ");
+ xSnprintf(buffer, n, "%*.*s ", width, width, "N/A");
}
}
@@ -886,13 +888,13 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
xSnprintf(buffer, n, "%4ld ", this->nlwp);
break;
- case PERCENT_CPU: Process_printPercentage(this->percent_cpu, buffer, n, &attr); break;
+ case PERCENT_CPU: Process_printPercentage(this->percent_cpu, buffer, n, Process_fieldWidths[PERCENT_CPU], &attr); break;
case PERCENT_NORM_CPU: {
float cpuPercentage = this->percent_cpu / this->processList->activeCPUs;
- Process_printPercentage(cpuPercentage, buffer, n, &attr);
+ Process_printPercentage(cpuPercentage, buffer, n, Process_fieldWidths[PERCENT_CPU], &attr);
break;
}
- case PERCENT_MEM: Process_printPercentage(this->percent_mem, buffer, n, &attr); break;
+ case PERCENT_MEM: Process_printPercentage(this->percent_mem, buffer, n, 4, &attr); break;
case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break;
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); break;
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->ppid); break;
@@ -1011,7 +1013,7 @@ void Process_done(Process* this) {
/* This function returns the string displayed in Command column, so that sorting
* happens on what is displayed - whether comm, full path, basename, etc.. So
* this follows Process_writeField(COMM) and Process_writeCommand */
-const char* Process_getCommandStr(const Process* this) {
+const char* Process_getCommand(const Process* this) {
if ((Process_isUserlandThread(this) && this->settings->showThreadNames) || !this->mergedCommand.str) {
return this->cmdline;
}
@@ -1027,7 +1029,6 @@ const ProcessClass Process_class = {
.compare = Process_compare
},
.writeField = Process_writeField,
- .getCommandStr = Process_getCommandStr,
};
void Process_init(Process* this, const Settings* settings) {
@@ -1251,3 +1252,36 @@ void Process_updateExe(Process* this, const char* exe) {
}
this->mergedCommand.exeChanged = true;
}
+
+uint8_t Process_fieldWidths[LAST_PROCESSFIELD] = { 0 };
+
+void Process_resetFieldWidths() {
+ for (size_t i = 0; i < LAST_PROCESSFIELD; i++) {
+ if (!Process_fields[i].autoWidth)
+ continue;
+
+ size_t len = strlen(Process_fields[i].title);
+ assert(len <= UINT8_MAX);
+ Process_fieldWidths[i] = (uint8_t)len;
+ }
+}
+
+void Process_updateFieldWidth(ProcessField key, size_t width) {
+ if (width > UINT8_MAX)
+ Process_fieldWidths[key] = UINT8_MAX;
+ else if (width > Process_fieldWidths[key])
+ Process_fieldWidths[key] = (uint8_t)width;
+}
+
+void Process_updateCPUFieldWidths(float percentage) {
+ if (percentage < 99.9) {
+ Process_updateFieldWidth(PERCENT_CPU, 4);
+ Process_updateFieldWidth(PERCENT_NORM_CPU, 4);
+ return;
+ }
+
+ uint8_t width = ceil(log10(percentage + .2));
+
+ Process_updateFieldWidth(PERCENT_CPU, width);
+ Process_updateFieldWidth(PERCENT_NORM_CPU, width);
+}
diff --git a/Process.h b/Process.h
index 26f64349..e1408c21 100644
--- a/Process.h
+++ b/Process.h
@@ -250,10 +250,10 @@ typedef struct Process_ {
* Internal state for tree-mode.
*/
int indent;
- unsigned int tree_left;
- unsigned int tree_right;
unsigned int tree_depth;
- unsigned int tree_index;
+
+ /* Has no known parent process */
+ bool isRoot;
/*
* Internal state for merged Command display
@@ -279,6 +279,9 @@ typedef struct ProcessFieldData_ {
/* Whether the column should be sorted in descending order by default */
bool defaultSortDesc;
+
+ /* Whether the column width is dynamically adjusted (the minimum width is determined by the title length) */
+ bool autoWidth;
} ProcessFieldData;
// Implemented in platform-specific code:
@@ -286,6 +289,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
int Process_compare(const void* v1, const void* v2);
void Process_delete(Object* cast);
extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD];
+extern uint8_t Process_fieldWidths[LAST_PROCESSFIELD];
#define PROCESS_MIN_PID_DIGITS 5
#define PROCESS_MAX_PID_DIGITS 19
#define PROCESS_MIN_UID_DIGITS 5
@@ -296,18 +300,15 @@ extern int Process_uidDigits;
typedef Process* (*Process_New)(const struct Settings_*);
typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField);
typedef int (*Process_CompareByKey)(const Process*, const Process*, ProcessField);
-typedef const char* (*Process_GetCommandStr)(const Process*);
typedef struct ProcessClass_ {
const ObjectClass super;
const Process_WriteField writeField;
const Process_CompareByKey compareByKey;
- const Process_GetCommandStr getCommandStr;
} ProcessClass;
#define As_Process(this_) ((const ProcessClass*)((this_)->super.klass))
-#define Process_getCommand(this_) (As_Process(this_)->getCommandStr ? As_Process(this_)->getCommandStr((const Process*)(this_)) : Process_getCommandStr((const Process*)(this_)))
#define Process_compareByKey(p1_, p2_, key_) (As_Process(p1_)->compareByKey ? (As_Process(p1_)->compareByKey(p1_, p2_, key_)) : Process_compareByKey_Base(p1_, p2_, key_))
static inline pid_t Process_getParentPid(const Process* this) {
@@ -371,7 +372,7 @@ void Process_fillStarttimeBuffer(Process* this);
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width);
-void Process_printPercentage(float val, char* buffer, int n, int* attr);
+void Process_printPercentage(float val, char* buffer, int n, uint8_t width, int* attr);
void Process_display(const Object* cast, RichString* out);
@@ -397,17 +398,20 @@ int Process_pidCompare(const void* v1, const void* v2);
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key);
-// Avoid direct calls, use Process_getCommand instead
-const char* Process_getCommandStr(const Process* this);
+const char* Process_getCommand(const Process* this);
void Process_updateComm(Process* this, const char* comm);
void Process_updateCmdline(Process* this, const char* cmdline, int basenameStart, int basenameEnd);
void Process_updateExe(Process* this, const char* exe);
/* This function constructs the string that is displayed by
- * Process_writeCommand and also returned by Process_getCommandStr */
+ * Process_writeCommand and also returned by Process_getCommand */
void Process_makeCommandStr(Process* this);
void Process_writeCommand(const Process* this, int attr, int baseAttr, RichString* str);
+void Process_resetFieldWidths(void);
+void Process_updateFieldWidth(ProcessField key, size_t width);
+void Process_updateCPUFieldWidths(float percentage);
+
#endif
diff --git a/ProcessList.c b/ProcessList.c
index 1df1990d..f3e184e8 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -22,11 +22,10 @@ in the source distribution for its full text.
ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId) {
this->processes = Vector_new(klass, true, DEFAULT_SIZE);
- this->processes2 = Vector_new(klass, true, DEFAULT_SIZE); // tree-view auxiliary buffer
+ this->displayList = Vector_new(klass, false, DEFAULT_SIZE);
this->processTable = Hashtable_new(200, false);
- this->displayTreeSet = Hashtable_new(200, false);
- this->draftingTreeSet = Hashtable_new(200, false);
+ this->needsSort = true;
this->usersTable = usersTable;
this->pidMatchList = pidMatchList;
@@ -73,11 +72,9 @@ void ProcessList_done(ProcessList* this) {
}
#endif
- Hashtable_delete(this->draftingTreeSet);
- Hashtable_delete(this->displayTreeSet);
Hashtable_delete(this->processTable);
- Vector_delete(this->processes2);
+ Vector_delete(this->displayList);
Vector_delete(this->processes);
}
@@ -117,6 +114,12 @@ static const char* alignedProcessFieldTitle(const ProcessList* this, ProcessFiel
return titleBuffer;
}
+ if (Process_fields[field].autoWidth) {
+ static char titleBuffer[UINT8_MAX + 1];
+ xSnprintf(titleBuffer, sizeof(titleBuffer), "%-*.*s ", Process_fieldWidths[field], Process_fieldWidths[field], title);
+ return titleBuffer;
+ }
+
return title;
}
@@ -194,308 +197,140 @@ void ProcessList_remove(ProcessList* this, const Process* p) {
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
}
-// ProcessList_updateTreeSetLayer sorts this->displayTreeSet,
-// relying only on itself.
-//
-// Algorithm
-//
-// The algorithm is based on `depth-first search`,
-// even though `breadth-first search` approach may be more efficient on first glance,
-// after comparison it may be not, as it's not safe to go deeper without first updating the tree structure.
-// If it would be safe that approach would likely bring an advantage in performance.
-//
-// Each call of the function looks for a 'layer'. A 'layer' is a list of processes with the same depth.
-// First it sorts a list. Then it runs the function recursively for each element of the sorted list.
-// After that it updates the settings of processes.
-//
-// It relies on `leftBound` and `rightBound` as an optimization to cut the list size at the time it builds a 'layer'.
-//
-// It uses a temporary Hashtable `draftingTreeSet` because it's not safe to traverse a tree
-// and at the same time make changes in it.
-//
-static void ProcessList_updateTreeSetLayer(ProcessList* this, unsigned int leftBound, unsigned int rightBound, unsigned int deep, unsigned int left, unsigned int right, unsigned int* index, unsigned int* treeIndex, int indent) {
-
- // It's guaranteed that layer_size is enough space
- // but most likely it needs less. Specifically on first iteration.
- int layerSize = (right - left) / 2;
-
- // check if we reach `children` of `leaves`
- if (layerSize == 0)
- return;
-
- Vector* layer = Vector_new(Vector_type(this->processes), false, layerSize);
-
- // Find all processes on the same layer (process with the same `deep` value
- // and included in a range from `leftBound` to `rightBound`).
- //
- // This loop also keeps track of left_bound and right_bound of these processes
- // in order not to lose this information once the list is sorted.
- //
- // The variables left_bound and right_bound are different from what the values lhs and rhs represent.
- // While left_bound and right_bound define a range of processes to look at, the values given by lhs and rhs are indices into an array
- //
- // In the below example note how filtering a range of indices i is different from filtering for processes in the bounds left_bound < x < right_bound …
- //
- // The nested tree set is sorted by left value, which is guaranteed upon entry/exit of this function.
- //
- // i | l | r
- // 1 | 1 | 9
- // 2 | 2 | 8
- // 3 | 4 | 5
- // 4 | 6 | 7
- for (unsigned int i = leftBound; i < rightBound; i++) {
- Process* proc = (Process*)Hashtable_get(this->displayTreeSet, i);
- assert(proc);
- if (proc && proc->tree_depth == deep && proc->tree_left > left && proc->tree_right < right) {
- if (Vector_size(layer) > 0) {
- Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1);
-
- // Make a 'right_bound' of previous_process in a layer the current process's index.
- //
- // Use 'tree_depth' as a temporal variable.
- // It's safe to do as later 'tree_depth' will be renovated.
- previous_process->tree_depth = proc->tree_index;
- }
-
- Vector_add(layer, proc);
- }
- }
-
- // The loop above changes just up to process-1.
- // So the last process of the layer isn't updated by the above code.
- //
- // Thus, if present, set the `rightBound` to the last process on the layer
- if (Vector_size(layer) > 0) {
- Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1);
- previous_process->tree_depth = rightBound;
- }
-
- Vector_quickSort(layer);
-
- int size = Vector_size(layer);
- for (int i = 0; i < size; i++) {
- Process* proc = (Process*)Vector_get(layer, i);
-
- unsigned int idx = (*index)++;
- int newLeft = (*treeIndex)++;
-
- int level = deep == 0 ? 0 : (int)deep - 1;
- int currentIndent = indent == -1 ? 0 : inden