Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
htop
Commits
da23c8c5
Commit
da23c8c5
authored
Mar 09, 2008
by
Hisham Muhammad
Browse files
Clean up headers by using 'static' whenever possible.
Reduces resulting code size.
parent
12f4f09e
Changes
64
Show whitespace changes
Inline
Side-by-side
ScreenManager.c
View file @
da23c8c5
...
...
@@ -98,12 +98,6 @@ Panel* ScreenManager_remove(ScreenManager* this, int index) {
return
panel
;
}
void
ScreenManager_setFunctionBar
(
ScreenManager
*
this
,
FunctionBar
*
fuBar
)
{
if
(
this
->
owner
&&
this
->
fuBar
)
FunctionBar_delete
((
Object
*
)
this
->
fuBar
);
this
->
fuBar
=
fuBar
;
}
void
ScreenManager_resize
(
ScreenManager
*
this
,
int
x1
,
int
y1
,
int
x2
,
int
y2
)
{
this
->
x1
=
x1
;
this
->
y1
=
y1
;
...
...
ScreenManager.h
View file @
da23c8c5
...
...
@@ -49,8 +49,6 @@ void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int
Panel
*
ScreenManager_remove
(
ScreenManager
*
this
,
int
index
);
void
ScreenManager_setFunctionBar
(
ScreenManager
*
this
,
FunctionBar
*
fuBar
);
void
ScreenManager_resize
(
ScreenManager
*
this
,
int
x1
,
int
y1
,
int
x2
,
int
y2
);
void
ScreenManager_run
(
ScreenManager
*
this
,
Panel
**
lastFocus
,
int
*
lastKey
);
...
...
Settings.c
View file @
da23c8c5
...
...
@@ -27,40 +27,6 @@ typedef struct Settings_ {
}*/
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
)
{
Settings
*
this
=
malloc
(
sizeof
(
Settings
));
this
->
pl
=
pl
;
this
->
header
=
header
;
char
*
home
;
char
*
rcfile
;
home
=
getenv
(
"HOME_ETC"
);
if
(
!
home
)
home
=
getenv
(
"HOME"
);
if
(
!
home
)
home
=
""
;
rcfile
=
getenv
(
"HOMERC"
);
if
(
!
rcfile
)
this
->
userSettings
=
String_cat
(
home
,
"/.htoprc"
);
else
this
->
userSettings
=
String_copy
(
rcfile
);
this
->
colorScheme
=
0
;
this
->
changed
=
false
;
this
->
delay
=
DEFAULT_DELAY
;
bool
ok
=
Settings_read
(
this
,
this
->
userSettings
);
if
(
!
ok
)
{
this
->
changed
=
true
;
// TODO: how to get SYSCONFDIR correctly through Autoconf?
char
*
systemSettings
=
String_cat
(
SYSCONFDIR
,
"/htoprc"
);
ok
=
Settings_read
(
this
,
systemSettings
);
free
(
systemSettings
);
if
(
!
ok
)
{
Header_defaultMeters
(
this
->
header
);
pl
->
hideKernelThreads
=
true
;
pl
->
highlightMegabytes
=
true
;
pl
->
highlightThreads
=
false
;
}
}
return
this
;
}
void
Settings_delete
(
Settings
*
this
)
{
free
(
this
->
userSettings
);
free
(
this
);
...
...
@@ -89,7 +55,7 @@ static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side)
String_freeArray
(
ids
);
}
bool
Settings_read
(
Settings
*
this
,
char
*
fileName
)
{
static
bool
Settings_read
(
Settings
*
this
,
char
*
fileName
)
{
// TODO: implement File object and make
// file I/O object-oriented.
FILE
*
fd
;
...
...
@@ -232,3 +198,37 @@ bool Settings_write(Settings* this) {
fclose
(
fd
);
return
true
;
}
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
)
{
Settings
*
this
=
malloc
(
sizeof
(
Settings
));
this
->
pl
=
pl
;
this
->
header
=
header
;
char
*
home
;
char
*
rcfile
;
home
=
getenv
(
"HOME_ETC"
);
if
(
!
home
)
home
=
getenv
(
"HOME"
);
if
(
!
home
)
home
=
""
;
rcfile
=
getenv
(
"HOMERC"
);
if
(
!
rcfile
)
this
->
userSettings
=
String_cat
(
home
,
"/.htoprc"
);
else
this
->
userSettings
=
String_copy
(
rcfile
);
this
->
colorScheme
=
0
;
this
->
changed
=
false
;
this
->
delay
=
DEFAULT_DELAY
;
bool
ok
=
Settings_read
(
this
,
this
->
userSettings
);
if
(
!
ok
)
{
this
->
changed
=
true
;
// TODO: how to get SYSCONFDIR correctly through Autoconf?
char
*
systemSettings
=
String_cat
(
SYSCONFDIR
,
"/htoprc"
);
ok
=
Settings_read
(
this
,
systemSettings
);
free
(
systemSettings
);
if
(
!
ok
)
{
Header_defaultMeters
(
this
->
header
);
pl
->
hideKernelThreads
=
true
;
pl
->
highlightMegabytes
=
true
;
pl
->
highlightThreads
=
false
;
}
}
return
this
;
}
Settings.h
View file @
da23c8c5
...
...
@@ -28,12 +28,10 @@ typedef struct Settings_ {
}
Settings
;
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
);
void
Settings_delete
(
Settings
*
this
);
bool
Settings_read
(
Settings
*
this
,
char
*
fileName
);
bool
Settings_write
(
Settings
*
this
);
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
);
#endif
SignalItem.c
View file @
da23c8c5
...
...
@@ -31,24 +31,14 @@ char* SIGNAL_CLASS = "Signal";
#define SIGNAL_CLASS NULL
#endif
Signal
*
Signal_new
(
char
*
name
,
int
number
)
{
Signal
*
this
=
malloc
(
sizeof
(
Signal
));
Object_setClass
(
this
,
SIGNAL_CLASS
);
((
Object
*
)
this
)
->
display
=
Signal_display
;
((
Object
*
)
this
)
->
delete
=
Signal_delete
;
this
->
name
=
name
;
this
->
number
=
number
;
return
this
;
}
void
Signal_delete
(
Object
*
cast
)
{
static
void
Signal_delete
(
Object
*
cast
)
{
Signal
*
this
=
(
Signal
*
)
cast
;
assert
(
this
!=
NULL
);
// names are string constants, so we're not deleting them.
free
(
this
);
}
void
Signal_display
(
Object
*
cast
,
RichString
*
out
)
{
static
void
Signal_display
(
Object
*
cast
,
RichString
*
out
)
{
Signal
*
this
=
(
Signal
*
)
cast
;
assert
(
this
!=
NULL
);
...
...
@@ -57,6 +47,16 @@ void Signal_display(Object* cast, RichString* out) {
RichString_write
(
out
,
CRT_colors
[
DEFAULT_COLOR
],
buffer
);
}
static
Signal
*
Signal_new
(
char
*
name
,
int
number
)
{
Signal
*
this
=
malloc
(
sizeof
(
Signal
));
Object_setClass
(
this
,
SIGNAL_CLASS
);
((
Object
*
)
this
)
->
display
=
Signal_display
;
((
Object
*
)
this
)
->
delete
=
Signal_delete
;
this
->
name
=
name
;
this
->
number
=
number
;
return
this
;
}
int
Signal_getSignalCount
()
{
return
SIGNAL_COUNT
;
}
...
...
SignalItem.h
View file @
da23c8c5
...
...
@@ -32,12 +32,6 @@ extern char* SIGNAL_CLASS;
#define SIGNAL_CLASS NULL
#endif
Signal
*
Signal_new
(
char
*
name
,
int
number
);
void
Signal_delete
(
Object
*
cast
);
void
Signal_display
(
Object
*
cast
,
RichString
*
out
);
int
Signal_getSignalCount
();
Signal
**
Signal_getSignalTable
();
...
...
SignalsPanel.c
View file @
da23c8c5
...
...
@@ -20,38 +20,7 @@ typedef struct SignalsPanel_ {
}*/
SignalsPanel
*
SignalsPanel_new
(
int
x
,
int
y
,
int
w
,
int
h
)
{
SignalsPanel
*
this
=
(
SignalsPanel
*
)
malloc
(
sizeof
(
SignalsPanel
));
Panel
*
super
=
(
Panel
*
)
this
;
Panel_init
(
super
,
x
,
y
,
w
,
h
,
SIGNAL_CLASS
,
true
);
((
Object
*
)
this
)
->
delete
=
SignalsPanel_delete
;
this
->
signals
=
Signal_getSignalTable
();
super
->
eventHandler
=
SignalsPanel_eventHandler
;
int
sigCount
=
Signal_getSignalCount
();
for
(
int
i
=
0
;
i
<
sigCount
;
i
++
)
Panel_set
(
super
,
i
,
(
Object
*
)
this
->
signals
[
i
]);
SignalsPanel_reset
(
this
);
return
this
;
}
void
SignalsPanel_delete
(
Object
*
object
)
{
Panel
*
super
=
(
Panel
*
)
object
;
SignalsPanel
*
this
=
(
SignalsPanel
*
)
object
;
Panel_done
(
super
);
free
(
this
->
signals
);
free
(
this
);
}
void
SignalsPanel_reset
(
SignalsPanel
*
this
)
{
Panel
*
super
=
(
Panel
*
)
this
;
Panel_setHeader
(
super
,
"Send signal:"
);
Panel_setSelected
(
super
,
16
);
// 16th item is SIGTERM
this
->
state
=
0
;
}
HandlerResult
SignalsPanel_eventHandler
(
Panel
*
super
,
int
ch
)
{
static
HandlerResult
SignalsPanel_eventHandler
(
Panel
*
super
,
int
ch
)
{
SignalsPanel
*
this
=
(
SignalsPanel
*
)
super
;
int
size
=
Panel_getSize
(
super
);
...
...
@@ -75,3 +44,34 @@ HandlerResult SignalsPanel_eventHandler(Panel* super, int ch) {
}
return
IGNORED
;
}
static
void
SignalsPanel_delete
(
Object
*
object
)
{
Panel
*
super
=
(
Panel
*
)
object
;
SignalsPanel
*
this
=
(
SignalsPanel
*
)
object
;
Panel_done
(
super
);
free
(
this
->
signals
);
free
(
this
);
}
SignalsPanel
*
SignalsPanel_new
(
int
x
,
int
y
,
int
w
,
int
h
)
{
SignalsPanel
*
this
=
(
SignalsPanel
*
)
malloc
(
sizeof
(
SignalsPanel
));
Panel
*
super
=
(
Panel
*
)
this
;
Panel_init
(
super
,
x
,
y
,
w
,
h
,
SIGNAL_CLASS
,
true
);
((
Object
*
)
this
)
->
delete
=
SignalsPanel_delete
;
this
->
signals
=
Signal_getSignalTable
();
super
->
eventHandler
=
SignalsPanel_eventHandler
;
int
sigCount
=
Signal_getSignalCount
();
for
(
int
i
=
0
;
i
<
sigCount
;
i
++
)
Panel_set
(
super
,
i
,
(
Object
*
)
this
->
signals
[
i
]);
SignalsPanel_reset
(
this
);
return
this
;
}
void
SignalsPanel_reset
(
SignalsPanel
*
this
)
{
Panel
*
super
=
(
Panel
*
)
this
;
Panel_setHeader
(
super
,
"Send signal:"
);
Panel_setSelected
(
super
,
16
);
// 16th item is SIGTERM
this
->
state
=
0
;
}
SignalsPanel.h
View file @
da23c8c5
...
...
@@ -23,10 +23,6 @@ typedef struct SignalsPanel_ {
SignalsPanel
*
SignalsPanel_new
(
int
x
,
int
y
,
int
w
,
int
h
);
void
SignalsPanel_delete
(
Object
*
object
);
void
SignalsPanel_reset
(
SignalsPanel
*
this
);
HandlerResult
SignalsPanel_eventHandler
(
Panel
*
super
,
int
ch
);
#endif
String.c
View file @
da23c8c5
...
...
@@ -18,10 +18,6 @@ in the source distribution for its full text.
#define String_startsWith(s, match) (strstr((s), (match)) == (s))
}*/
inline
void
String_delete
(
char
*
s
)
{
free
(
s
);
}
inline
char
*
String_copy
(
char
*
orig
)
{
return
strdup
(
orig
);
}
...
...
@@ -49,53 +45,6 @@ char* String_trim(char* in) {
return
out
;
}
char
*
String_copyUpTo
(
char
*
orig
,
char
upTo
)
{
int
len
;
int
origLen
=
strlen
(
orig
);
char
*
at
=
strchr
(
orig
,
upTo
);
if
(
at
!=
NULL
)
len
=
at
-
orig
;
else
len
=
origLen
;
char
*
copy
=
(
char
*
)
malloc
(
len
+
1
);
strncpy
(
copy
,
orig
,
len
);
copy
[
len
]
=
'\0'
;
return
copy
;
}
char
*
String_sub
(
char
*
orig
,
int
from
,
int
to
)
{
char
*
copy
;
int
len
;
len
=
strlen
(
orig
);
if
(
to
>
len
)
to
=
len
;
if
(
from
>
len
)
to
=
len
;
len
=
to
-
from
+
1
;
copy
=
(
char
*
)
malloc
(
len
+
1
);
strncpy
(
copy
,
orig
+
from
,
len
);
copy
[
len
]
=
'\0'
;
return
copy
;
}
void
String_println
(
char
*
s
)
{
printf
(
"%s
\n
"
,
s
);
}
void
String_print
(
char
*
s
)
{
printf
(
"%s"
,
s
);
}
void
String_printInt
(
int
i
)
{
printf
(
"%i"
,
i
);
}
void
String_printPointer
(
void
*
p
)
{
printf
(
"%p"
,
p
);
}
inline
int
String_eq
(
const
char
*
s1
,
const
char
*
s2
)
{
if
(
s1
==
NULL
||
s2
==
NULL
)
{
if
(
s1
==
NULL
&&
s2
==
NULL
)
...
...
@@ -144,10 +93,6 @@ void String_freeArray(char** s) {
free
(
s
);
}
int
String_startsWith_i
(
char
*
s
,
char
*
match
)
{
return
(
strncasecmp
(
s
,
match
,
strlen
(
match
))
==
0
);
}
int
String_contains_i
(
char
*
s
,
char
*
match
)
{
int
lens
=
strlen
(
s
);
int
lenmatch
=
strlen
(
match
);
...
...
String.h
View file @
da23c8c5
...
...
@@ -19,34 +19,18 @@ in the source distribution for its full text.
#define String_startsWith(s, match) (strstr((s), (match)) == (s))
extern
void
String_delete
(
char
*
s
);
extern
char
*
String_copy
(
char
*
orig
);
char
*
String_cat
(
char
*
s1
,
char
*
s2
);
char
*
String_trim
(
char
*
in
);
char
*
String_copyUpTo
(
char
*
orig
,
char
upTo
);
char
*
String_sub
(
char
*
orig
,
int
from
,
int
to
);
void
String_println
(
char
*
s
);
void
String_print
(
char
*
s
);
void
String_printInt
(
int
i
);
void
String_printPointer
(
void
*
p
);
extern
int
String_eq
(
const
char
*
s1
,
const
char
*
s2
);
char
**
String_split
(
char
*
s
,
char
sep
);
void
String_freeArray
(
char
**
s
);
int
String_startsWith_i
(
char
*
s
,
char
*
match
);
int
String_contains_i
(
char
*
s
,
char
*
match
);
#endif
SwapMeter.c
View file @
da23c8c5
...
...
@@ -23,26 +23,14 @@ int SwapMeter_attributes[] = {
SWAP
};
MeterType
SwapMeter
=
{
.
setValues
=
SwapMeter_setValues
,
.
display
=
SwapMeter_display
,
.
mode
=
BAR_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
SwapMeter_attributes
,
.
name
=
"Swap"
,
.
uiName
=
"Swap"
,
.
caption
=
"Swp"
};
void
SwapMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
static
void
SwapMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
long
int
usedSwap
=
this
->
pl
->
usedSwap
;
this
->
total
=
this
->
pl
->
totalSwap
;
this
->
values
[
0
]
=
usedSwap
;
snprintf
(
buffer
,
len
,
"%ld/%ldMB"
,
(
long
int
)
usedSwap
/
1024
,
(
long
int
)
this
->
total
/
1024
);
}
void
SwapMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
static
void
SwapMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
char
buffer
[
50
];
Meter
*
this
=
(
Meter
*
)
cast
;
long
int
swap
=
(
long
int
)
this
->
values
[
0
];
...
...
@@ -54,3 +42,15 @@ void SwapMeter_display(Object* cast, RichString* out) {
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
"used:"
);
RichString_append
(
out
,
CRT_colors
[
METER_VALUE
],
buffer
);
}
MeterType
SwapMeter
=
{
.
setValues
=
SwapMeter_setValues
,
.
display
=
SwapMeter_display
,
.
mode
=
BAR_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
SwapMeter_attributes
,
.
name
=
"Swap"
,
.
uiName
=
"Swap"
,
.
caption
=
"Swp"
};
SwapMeter.h
View file @
da23c8c5
...
...
@@ -26,8 +26,4 @@ extern int SwapMeter_attributes[];
extern
MeterType
SwapMeter
;
void
SwapMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
);
void
SwapMeter_display
(
Object
*
cast
,
RichString
*
out
);
#endif
TasksMeter.c
View file @
da23c8c5
...
...
@@ -18,25 +18,13 @@ int TasksMeter_attributes[] = {
TASKS_RUNNING
};
MeterType
TasksMeter
=
{
.
setValues
=
TasksMeter_setValues
,
.
display
=
TasksMeter_display
,
.
mode
=
TEXT_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
TasksMeter_attributes
,
.
name
=
"Tasks"
,
.
uiName
=
"Task counter"
,
.
caption
=
"Tasks: "
};
void
TasksMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
static
void
TasksMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
this
->
total
=
this
->
pl
->
totalTasks
;
this
->
values
[
0
]
=
this
->
pl
->
runningTasks
;
snprintf
(
buffer
,
len
,
"%d/%d"
,
(
int
)
this
->
values
[
0
],
(
int
)
this
->
total
);
}
void
TasksMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
static
void
TasksMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
Meter
*
this
=
(
Meter
*
)
cast
;
RichString_init
(
out
);
char
buffer
[
20
];
...
...
@@ -47,3 +35,15 @@ void TasksMeter_display(Object* cast, RichString* out) {
RichString_append
(
out
,
CRT_colors
[
TASKS_RUNNING
],
buffer
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
" running"
);
}
MeterType
TasksMeter
=
{
.
setValues
=
TasksMeter_setValues
,
.
display
=
TasksMeter_display
,
.
mode
=
TEXT_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
TasksMeter_attributes
,
.
name
=
"Tasks"
,
.
uiName
=
"Task counter"
,
.
caption
=
"Tasks: "
};
TasksMeter.h
View file @
da23c8c5
...
...
@@ -21,8 +21,4 @@ extern int TasksMeter_attributes[];
extern
MeterType
TasksMeter
;
void
TasksMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
);
void
TasksMeter_display
(
Object
*
cast
,
RichString
*
out
);
#endif
TraceScreen.c
View file @
da23c8c5
...
...
@@ -53,7 +53,7 @@ void TraceScreen_delete(TraceScreen* this) {
free
(
this
);
}
void
TraceScreen_draw
(
TraceScreen
*
this
)
{
static
void
TraceScreen_draw
(
TraceScreen
*
this
)
{
attrset
(
CRT_colors
[
PANEL_HEADER_FOCUS
]);
mvhline
(
0
,
0
,
' '
,
COLS
);
mvprintw
(
0
,
0
,
"Trace of process %d - %s"
,
this
->
process
->
pid
,
this
->
process
->
comm
);
...
...
TraceScreen.h
View file @
da23c8c5
...
...
@@ -37,8 +37,6 @@ TraceScreen* TraceScreen_new(Process* process);
void
TraceScreen_delete
(
TraceScreen
*
this
);
void
TraceScreen_draw
(
TraceScreen
*
this
);
void
TraceScreen_run
(
TraceScreen
*
this
);
#endif
UptimeMeter.c
View file @
da23c8c5
...
...
@@ -18,19 +18,7 @@ int UptimeMeter_attributes[] = {
UPTIME
};
MeterType
UptimeMeter
=
{
.
setValues
=
UptimeMeter_setValues
,
.
display
=
NULL
,
.
mode
=
TEXT_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
UptimeMeter_attributes
,
.
name
=
"Uptime"
,
.
uiName
=
"Uptime"
,
.
caption
=
"Uptime: "
};
void
UptimeMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
static
void
UptimeMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
double
uptime
;
FILE
*
fd
=
fopen
(
PROCDIR
"/uptime"
,
"r"
);
fscanf
(
fd
,
"%lf"
,
&
uptime
);
...
...
@@ -56,3 +44,15 @@ void UptimeMeter_setValues(Meter* this, char* buffer, int len) {
}
snprintf
(
buffer
,
len
,
"%s%02d:%02d:%02d"
,
daysbuf
,
hours
,
minutes
,
seconds
);
}
MeterType
UptimeMeter
=
{
.
setValues
=
UptimeMeter_setValues
,
.
display
=
NULL
,
.
mode
=
TEXT_METERMODE
,
.
items
=
1
,
.
total
=
100
.
0
,
.
attributes
=
UptimeMeter_attributes
,
.
name
=
"Uptime"
,
.
uiName
=
"Uptime"
,
.
caption
=
"Uptime: "
};
UptimeMeter.h
View file @
da23c8c5
...
...
@@ -21,6 +21,4 @@ extern int UptimeMeter_attributes[];
extern
MeterType
UptimeMeter
;
void
UptimeMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
);
#endif
UsersTable.c
View file @
da23c8c5
...
...
@@ -47,10 +47,6 @@ char* UsersTable_getRef(UsersTable* this, unsigned int uid) {
return
name
;
}
inline
int
UsersTable_size
(
UsersTable
*
this
)
{
return
(
Hashtable_size
(
this
->
users
));
}
inline
void
UsersTable_foreach
(
UsersTable
*
this
,
Hashtable_PairFunction
f
,
void
*
userData
)
{
Hashtable_foreach
(
this
->
users
,
f
,
userData
);
}
UsersTable.h
View file @
da23c8c5
...
...
@@ -30,8 +30,6 @@ void UsersTable_delete(UsersTable* this);
char
*
UsersTable_getRef
(
UsersTable
*
this
,
unsigned
int
uid
);
extern
int
UsersTable_size
(
UsersTable
*
this
);
extern
void
UsersTable_foreach
(
UsersTable
*
this
,
Hashtable_PairFunction
f
,
void
*
userData
);
#endif
Prev
1
2
3
4
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment