2
* nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
5
* Copyright (C) 2004 NVIDIA Corporation.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of Version 2 of the GNU General Public
9
* License as published by the Free Software Foundation.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
14
* of the GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the:
19
* Free Software Foundation, Inc.
20
* 59 Temple Place - Suite 330
21
* Boston, MA 02111-1307, USA
29
#include <sys/utsname.h>
34
#include "NvCtrlAttributes.h"
36
/* local helper functions */
38
static char **nv_strtok(char *s, char c, int *n);
39
static void nv_free_strtoks(char **s, int n);
40
static int ctoi(const char c);
41
static int count_number_of_chars(char *o, char d);
42
static char *nv_strndup(char *s, int n);
45
* Table of all attribute names recognized by the attribute string
46
* parser. Binds attribute names to attribute integers (for use in
47
* the NvControl protocol). The flags describe qualities of each
51
#define F NV_PARSER_TYPE_FRAMELOCK
52
#define C NV_PARSER_TYPE_COLOR_ATTRIBUTE
53
#define N NV_PARSER_TYPE_NO_CONFIG_WRITE
54
#define G NV_PARSER_TYPE_GUI_ATTRIUBUTE
55
#define V NV_PARSER_TYPE_XVIDEO_ATTRIBUTE
57
AttributeTableEntry attributeTable[] = {
59
/* name constant flags */
61
{ "FlatpanelScaling", NV_CTRL_FLATPANEL_SCALING, 0 },
62
{ "FlatpanelDithering", NV_CTRL_FLATPANEL_DITHERING, 0 },
63
{ "DigitalVibrance", NV_CTRL_DIGITAL_VIBRANCE, 0 },
64
{ "ImageSharpening", NV_CTRL_IMAGE_SHARPENING, 0, },
65
{ "BusType", NV_CTRL_BUS_TYPE, 0 },
66
{ "VideoRam", NV_CTRL_VIDEO_RAM, 0 },
67
{ "Irq", NV_CTRL_IRQ, 0 },
68
{ "OperatingSystem", NV_CTRL_OPERATING_SYSTEM, 0 },
69
{ "SyncToVBlank", NV_CTRL_SYNC_TO_VBLANK, 0 },
70
{ "LogAniso", NV_CTRL_LOG_ANISO, 0 },
71
{ "FSAA", NV_CTRL_FSAA_MODE, 0 },
72
{ "TextureSharpen", NV_CTRL_TEXTURE_SHARPEN, 0 },
73
{ "Ubb", NV_CTRL_UBB, 0 },
74
{ "Overlay", NV_CTRL_OVERLAY, 0 },
75
{ "Stereo", NV_CTRL_STEREO, 0 },
76
{ "TwinView", NV_CTRL_TWINVIEW, 0 },
77
{ "ConnectedDisplays", NV_CTRL_CONNECTED_DISPLAYS, 0 },
78
{ "EnabledDisplays", NV_CTRL_ENABLED_DISPLAYS, 0 },
79
{ "ForceGenericCpu", NV_CTRL_FORCE_GENERIC_CPU, 0 },
80
{ "GammaCorrectedAALines", NV_CTRL_OPENGL_AA_LINE_GAMMA, 0 },
81
{ "CursorShadow", NV_CTRL_CURSOR_SHADOW, 0 },
82
{ "CursorShadowXOffset", NV_CTRL_CURSOR_SHADOW_X_OFFSET, 0 },
83
{ "CursorShadowYOffset", NV_CTRL_CURSOR_SHADOW_Y_OFFSET, 0 },
84
{ "CursorShadowAlpha", NV_CTRL_CURSOR_SHADOW_ALPHA, 0 },
85
{ "CursorShadowRed", NV_CTRL_CURSOR_SHADOW_RED, 0 },
86
{ "CursorShadowGreen", NV_CTRL_CURSOR_SHADOW_GREEN, 0 },
87
{ "CursorShadowBlue", NV_CTRL_CURSOR_SHADOW_BLUE, 0 },
88
{ "FSAAAppControlled", NV_CTRL_FSAA_APPLICATION_CONTROLLED, 0 },
89
{ "LogAnisoAppControlled", NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED,0 },
90
{ "FrameLockMaster", NV_CTRL_FRAMELOCK_MASTER, N|F|G },
91
{ "FrameLockPolarity", NV_CTRL_FRAMELOCK_POLARITY, N|F|G },
92
{ "FrameLockSyncDelay", NV_CTRL_FRAMELOCK_SYNC_DELAY, N|F|G },
93
{ "FrameLockEnable", NV_CTRL_FRAMELOCK_SYNC, N|F|G },
94
{ "FrameLockSyncInterval", NV_CTRL_FRAMELOCK_SYNC_INTERVAL, N|F|G },
95
{ "FrameLockHouseFormat", NV_CTRL_FRAMELOCK_VIDEO_MODE, N|F|G },
96
{ "Brightness", BRIGHTNESS_VALUE|ALL_CHANNELS, N|C|G },
97
{ "RedBrightness", BRIGHTNESS_VALUE|RED_CHANNEL, C|G },
98
{ "GreenBrightness", BRIGHTNESS_VALUE|GREEN_CHANNEL, C|G },
99
{ "BlueBrightness", BRIGHTNESS_VALUE|BLUE_CHANNEL, C|G },
100
{ "Contrast", CONTRAST_VALUE|ALL_CHANNELS, N|C|G },
101
{ "RedContrast", CONTRAST_VALUE|RED_CHANNEL, C|G },
102
{ "GreenContrast", CONTRAST_VALUE|GREEN_CHANNEL, C|G },
103
{ "BlueContrast", CONTRAST_VALUE|BLUE_CHANNEL, C|G },
104
{ "Gamma", GAMMA_VALUE|ALL_CHANNELS, N|C|G },
105
{ "RedGamma", GAMMA_VALUE|RED_CHANNEL, C|G },
106
{ "GreenGamma", GAMMA_VALUE|GREEN_CHANNEL, C|G },
107
{ "BlueGamma", GAMMA_VALUE|BLUE_CHANNEL, C|G },
108
{ "TVOverScan", NV_CTRL_TV_OVERSCAN, 0, },
109
{ "TVFlickerFilter", NV_CTRL_TV_FLICKER_FILTER, 0, },
110
{ "TVBrightness", NV_CTRL_TV_BRIGHTNESS, 0, },
111
{ "TVHue", NV_CTRL_TV_HUE, 0, },
112
{ "TVContrast", NV_CTRL_TV_CONTRAST, 0, },
113
{ "TVSaturation", NV_CTRL_TV_SATURATION, 0, },
114
{ "GPUCoreTemp", NV_CTRL_GPU_CORE_TEMPERATURE, N },
115
{ "GPUAmbientTemp", NV_CTRL_AMBIENT_TEMPERATURE, N },
117
{ "XVideoOverlaySaturation", NV_CTRL_ATTR_XV_OVERLAY_SATURATION, V },
118
{ "XVideoOverlayContrast", NV_CTRL_ATTR_XV_OVERLAY_CONTRAST, V },
119
{ "XVideoOverlayBrightness", NV_CTRL_ATTR_XV_OVERLAY_BRIGHTNESS, V },
120
{ "XVideoOverlayHue", NV_CTRL_ATTR_XV_OVERLAY_HUE, V },
121
{ "XVideoTextureSyncToVBlank", NV_CTRL_ATTR_XV_TEXTURE_SYNC_TO_VBLANK, V },
122
{ "XVideoBlitterSyncToVBlank", NV_CTRL_ATTR_XV_BLITTER_SYNC_TO_VBLANK, V },
134
* nv_parse_attribute_string() - see comments in parse.h
137
int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a)
139
char *s, *tmp, *name, *start, *display_device_name, *no_spaces = NULL;
140
char tmpname[NV_PARSER_MAX_NAME_LEN];
141
AttributeTableEntry *t;
142
int len, digits_only;
144
#define stop(x) { if (no_spaces) free(no_spaces); return (x); }
146
if (!a) stop(NV_PARSER_STATUS_BAD_ARGUMENT);
148
/* clear the ParsedAttribute struct */
150
memset((void *) a, 0, sizeof(ParsedAttribute));
152
/* remove any white space from the string, to simplify parsing */
154
no_spaces = remove_spaces(str);
155
if (!no_spaces) stop(NV_PARSER_STATUS_EMPTY_STRING);
158
* get the display name... ie: everything before the
159
* DISPLAY_NAME_SEPARATOR
162
s = strchr(no_spaces, DISPLAY_NAME_SEPARATOR);
165
* If we found a DISPLAY_NAME_SEPARATOR, and there is some text
166
* before it, it is either a screen number (if all characters
167
* between no_spaces and s are digits), or a display name.
170
if ((s) && (s != no_spaces)) {
172
/* are all characters numeric? */
174
digits_only = NV_TRUE;
176
for (tmp = no_spaces; tmp != s; tmp++) {
177
if (!isdigit(*tmp)) {
178
digits_only = NV_FALSE;
182
a->screen += ctoi(*tmp);
187
a->flags |= NV_PARSER_HAS_X_SCREEN;
189
a->display = nv_strndup(no_spaces, s - no_spaces);
190
a->flags |= NV_PARSER_HAS_X_DISPLAY;
193
* this will attempt to parse out any screen number from the
197
nv_assign_default_display(a, NULL);
201
/* move past the DISPLAY_NAME_SEPARATOR */
206
/* read the attribute name */
210
while (*s && isalnum(*s)) { s++; len++; }
212
if (len == 0) stop(NV_PARSER_STATUS_ATTR_NAME_MISSING);
213
if (len >= NV_PARSER_MAX_NAME_LEN)
214
stop(NV_PARSER_STATUS_ATTR_NAME_TOO_LONG);
216
strncpy(tmpname, name, len);
219
/* look up the requested name */
221
for (t = attributeTable; t->name; t++) {
222
if (nv_strcasecmp(tmpname, t->name)) {
225
a->flags |= t->flags;
230
if (!a->name) stop(NV_PARSER_STATUS_UNKNOWN_ATTR_NAME);
232
/* read the display device name, if any */
237
while (*s && *s != ']') s++;
238
display_device_name = nv_strndup(start, s - start);
239
a->display_device_mask =
240
display_device_name_to_display_device_mask(display_device_name);
241
if (a->display_device_mask == INVALID_DISPLAY_DEVICE_MASK)
242
stop(NV_PARSER_STATUS_BAD_DISPLAY_DEVICE);
243
a->flags |= NV_PARSER_HAS_DISPLAY_DEVICE;
247
if (query == NV_PARSER_ASSIGNMENT) {
249
/* there should be an equal sign */
252
else stop(NV_PARSER_STATUS_MISSING_EQUAL_SIGN);
257
if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
258
/* color attributes are floating point */
259
a->fval = strtod(s, &tmp);
261
/* all other attributes are integer */
262
a->val = strtol(s, &tmp, 10);
265
if (tmp && (s != tmp)) a->flags |= NV_PARSER_HAS_VAL;
268
if (!(a->flags & NV_PARSER_HAS_VAL)) stop(NV_PARSER_STATUS_NO_VALUE);
271
/* this should be the end of the string */
273
if (*s != '\0') stop(NV_PARSER_STATUS_TRAILING_GARBAGE);
275
stop(NV_PARSER_STATUS_SUCCESS);
277
} /* nv_parse_attribute_string() */
282
* nv_parse_strerror() - given the error status returned by
283
* nv_parse_attribute_string(), return a string describing the
287
char *nv_parse_strerror(int status)
290
case NV_PARSER_STATUS_SUCCESS :
291
return "No error"; break;
292
case NV_PARSER_STATUS_BAD_ARGUMENT :
293
return "Bad argument"; break;
294
case NV_PARSER_STATUS_EMPTY_STRING :
295
return "Emtpy string"; break;
296
case NV_PARSER_STATUS_ATTR_NAME_TOO_LONG :
297
return "The attribute name is too long"; break;
298
case NV_PARSER_STATUS_ATTR_NAME_MISSING :
299
return "Missing attribute name"; break;
300
case NV_PARSER_STATUS_BAD_DISPLAY_DEVICE :
301
return "Malformed display device identification"; break;
302
case NV_PARSER_STATUS_MISSING_EQUAL_SIGN :
303
return "Missing equal sign after attribute name"; break;
304
case NV_PARSER_STATUS_NO_VALUE :
305
return "No attribute value specified"; break;
306
case NV_PARSER_STATUS_TRAILING_GARBAGE :
307
return "Trailing garbage"; break;
308
case NV_PARSER_STATUS_UNKNOWN_ATTR_NAME :
309
return "Unrecognized attribute name"; break;
311
return "Unknown error"; break;
313
} /* nv_parse_strerror() */
318
* *sigh* strcasecmp() is a BSDism, and when building with "-ansi" we
319
* don't get the prototype, so reimplement it to avoid a compiler
320
* warning. Returns NV_TRUE if a match, returns NV_FALSE if there is
324
int nv_strcasecmp(const char *a, const char *b)
326
if (!a && !b) return NV_TRUE;
327
if (!a && b) return NV_FALSE;
328
if ( a && !b) return NV_FALSE;
330
while (toupper(*a) == toupper(*b)) {
333
if ((*a == '\0') && (*b == '\0')) return NV_TRUE;
338
} /* nv_strcasecmp() */
343
* display_name_to_display_device_mask() - parse the string that describes a
344
* display device mask; the string is a comma-separated list of
345
* display device names, where valid names are:
347
* CRT-[0,7] TV-[0,7] and DFP[0,7]
349
* Non-specific names ("CRT", "TV", and "DFP") are also allowed; if
350
* these are specified, then the appropriate WILDCARD flag in the
351
* upper-most byte of the display device mask is set:
353
* DISPLAY_DEVICES_WILDCARD_CRT
354
* DISPLAY_DEVICES_WILDCARD_TV
355
* DISPLAY_DEVICES_WILDCARD_DFP
357
* If a parse error occurs, INVALID_DISPLAY_DEVICE_MASK is returned,
358
* otherwise the display mask is returned.
362
uint32 display_device_name_to_display_device_mask(const char *str)
370
if (!str || !*str) return INVALID_DISPLAY_DEVICE_MASK;
372
/* remove spaces from the string */
374
s = remove_spaces(str);
375
if (!s || !*s) return INVALID_DISPLAY_DEVICE_MASK;
377
/* break up the string by commas */
379
toks = nv_strtok(s, ',', &n);
382
return INVALID_DISPLAY_DEVICE_MASK;
385
/* match each token, updating mask as appropriate */
387
for (i = 0; i < n; i++) {
389
if (nv_strcasecmp(toks[i], "CRT-0")) mask |= ((1 << 0) << 0);
390
else if (nv_strcasecmp(toks[i], "CRT-1")) mask |= ((1 << 1) << 0);
391
else if (nv_strcasecmp(toks[i], "CRT-2")) mask |= ((1 << 2) << 0);
392
else if (nv_strcasecmp(toks[i], "CRT-3")) mask |= ((1 << 3) << 0);
393
else if (nv_strcasecmp(toks[i], "CRT-4")) mask |= ((1 << 4) << 0);
394
else if (nv_strcasecmp(toks[i], "CRT-5")) mask |= ((1 << 5) << 0);
395
else if (nv_strcasecmp(toks[i], "CRT-6")) mask |= ((1 << 6) << 0);
396
else if (nv_strcasecmp(toks[i], "CRT-7")) mask |= ((1 << 7) << 0);
398
else if (nv_strcasecmp(toks[i], "TV-0" )) mask |= ((1 << 0) << 8);
399
else if (nv_strcasecmp(toks[i], "TV-1" )) mask |= ((1 << 1) << 8);
400
else if (nv_strcasecmp(toks[i], "TV-2" )) mask |= ((1 << 2) << 8);
401
else if (nv_strcasecmp(toks[i], "TV-3" )) mask |= ((1 << 3) << 8);
402
else if (nv_strcasecmp(toks[i], "TV-4" )) mask |= ((1 << 4) << 8);
403
else if (nv_strcasecmp(toks[i], "TV-5" )) mask |= ((1 << 5) << 8);
404
else if (nv_strcasecmp(toks[i], "TV-6" )) mask |= ((1 << 6) << 8);
405
else if (nv_strcasecmp(toks[i], "TV-7" )) mask |= ((1 << 7) << 8);
407
else if (nv_strcasecmp(toks[i], "DFP-0")) mask |= ((1 << 0) << 16);
408
else if (nv_strcasecmp(toks[i], "DFP-1")) mask |= ((1 << 1) << 16);
409
else if (nv_strcasecmp(toks[i], "DFP-2")) mask |= ((1 << 2) << 16);
410
else if (nv_strcasecmp(toks[i], "DFP-3")) mask |= ((1 << 3) << 16);
411
else if (nv_strcasecmp(toks[i], "DFP-4")) mask |= ((1 << 4) << 16);
412
else if (nv_strcasecmp(toks[i], "DFP-5")) mask |= ((1 << 5) << 16);
413
else if (nv_strcasecmp(toks[i], "DFP-6")) mask |= ((1 << 6) << 16);
414
else if (nv_strcasecmp(toks[i], "DFP-7")) mask |= ((1 << 7) << 16);
416
else if (nv_strcasecmp(toks[i], "CRT"))
417
mask |= DISPLAY_DEVICES_WILDCARD_CRT;
419
else if (nv_strcasecmp(toks[i], "TV"))
420
mask |= DISPLAY_DEVICES_WILDCARD_TV;
422
else if (nv_strcasecmp(toks[i], "DFP"))
423
mask |= DISPLAY_DEVICES_WILDCARD_DFP;
426
mask = INVALID_DISPLAY_DEVICE_MASK;
431
nv_free_strtoks(toks, n);
437
} /* display_name_to_display_device_mask() */
442
* display_device_mask_to_display_name() - construct a string
443
* describing the given display device mask. The returned pointer
444
* points to a global character buffer, so subsequent calls to
445
* display_device_mask_to_display_device_name() will clobber the
449
#define DISPLAY_DEVICE_STRING_LEN 256
451
char *display_device_mask_to_display_device_name(const uint32 mask)
455
uint32 devcnt, devmask;
456
char *display_device_name_string;
458
display_device_name_string = malloc(DISPLAY_DEVICE_STRING_LEN);
460
s = display_device_name_string;
462
devmask = 1 << BITSHIFT_CRT;
464
while (devmask & BITMASK_ALL_CRT) {
465
if (devmask & mask) {
466
if (first) first = NV_FALSE;
467
else s += sprintf(s, ", ");
468
s += sprintf(s, "CRT-%X", devcnt);
474
devmask = 1 << BITSHIFT_DFP;
476
while (devmask & BITMASK_ALL_DFP) {
477
if (devmask & mask) {
478
if (first) first = NV_FALSE;
479
else s += sprintf(s, ", ");
480
s += sprintf(s, "DFP-%X", devcnt);
486
devmask = 1 << BITSHIFT_TV;
488
while (devmask & BITMASK_ALL_TV) {
489
if (devmask & mask) {
490
if (first) first = NV_FALSE;
491
else s += sprintf(s, ", ");
492
s += sprintf(s, "TV-%X", devcnt);
498
if (mask & DISPLAY_DEVICES_WILDCARD_CRT) {
499
if (first) first = NV_FALSE;
500
else s += sprintf(s, ", ");
501
s += sprintf(s, "CRT");
504
if (mask & DISPLAY_DEVICES_WILDCARD_TV) {
505
if (first) first = NV_FALSE;
506
else s += sprintf(s, ", ");
507
s += sprintf(s, "TV");
510
if (mask & DISPLAY_DEVICES_WILDCARD_DFP) {
511
if (first) first = NV_FALSE;
512
else s += sprintf(s, ", ");
513
s += sprintf(s, "DFP");
518
return (display_device_name_string);
520
} /* display_device_mask_to_display_name() */
525
* expand_display_device_mask_wildcards() - build a display mask by
526
* taking any of the real display mask bits; if there are any wildcard
527
* flags set, or in all display devices of that type into the display
531
uint32 expand_display_device_mask_wildcards(const uint32 d, const uint32 e)
533
uint32 mask = d & VALID_DISPLAY_DEVICES_MASK;
535
if (d & DISPLAY_DEVICES_WILDCARD_CRT) mask |= (e & BITMASK_ALL_CRT);
536
if (d & DISPLAY_DEVICES_WILDCARD_TV) mask |= (e & BITMASK_ALL_TV);
537
if (d & DISPLAY_DEVICES_WILDCARD_DFP) mask |= (e & BITMASK_ALL_DFP);
541
} /* expand_display_device_mask_wildcards() */
546
* nv_assign_default_display() - assign an X display, if none has been
547
* assigned already. Also, parse the the display name to find any
548
* specified X screen.
551
void nv_assign_default_display(ParsedAttribute *a, const char *display)
553
char *colon, *dot, *s;
555
if (!(a->flags & NV_PARSER_HAS_X_DISPLAY)) {
556
if (display) a->display = strdup(display);
557
else a->display = NULL;
558
a->flags |= NV_PARSER_HAS_X_DISPLAY;
561
if (!(a->flags & NV_PARSER_HAS_X_SCREEN) && a->display) {
562
colon = strchr(a->display, ':');
564
dot = strchr(colon, '.');
568
while (*s && isdigit(*s)) {
570
a->screen += ctoi(*s);
571
a->flags |= NV_PARSER_HAS_X_SCREEN;
577
} /* nv_assign_default_display() */
582
* nv_parsed_attribute_init() - initialize a ParsedAttribute linked
586
ParsedAttribute *nv_parsed_attribute_init(void)
588
ParsedAttribute *p = calloc(1, sizeof(ParsedAttribute));
594
} /* nv_parsed_attribute_init() */
599
* nv_parsed_attribute_add() - add a new parsed attribute node to the
603
void nv_parsed_attribute_add(ParsedAttribute *head, ParsedAttribute *a)
605
ParsedAttribute *p, *t;
607
p = calloc(1, sizeof(ParsedAttribute));
611
for (t = head; t->next; t = t->next);
615
if (a->display) t->display = strdup(a->display);
616
else t->display = NULL;
618
t->screen = a->screen;
622
t->display_device_mask = a->display_device_mask;
625
} /* nv_parsed_attribute_add() */
630
* nv_parsed_attribute_free() - free the linked list
633
void nv_parsed_attribute_free(ParsedAttribute *p)
639
if (p->display) free(p->display);
644
} /* nv_parsed_attribute_free() */
649
* nv_parsed_attribute_clean() - clean out the ParsedAttribute list,
650
* so that only the empty head node remains.
653
void nv_parsed_attribute_clean(ParsedAttribute *p)
655
nv_parsed_attribute_free(p->next);
657
if (p->display) free(p->display);
658
if (p->name) free(p->name);
660
memset(p, 0, sizeof(ParsedAttribute));
662
} /* nv_parsed_attribute_clean() */
667
* nv_get_attribute_name() - scan the attributeTable for the name that
668
* corresponds to the attribute constant.
671
char *nv_get_attribute_name(const int attr)
675
for (i = 0; attributeTable[i].name; i++) {
676
if (attributeTable[i].attr == attr) return attributeTable[i].name;
681
} /* nv_get_attribute_name() */
684
char *nv_standardize_screen_name(const char *orig, int screen)
686
char *display_name, *screen_name, *colon, *dot, *tmp;
687
struct utsname uname_buf;
690
/* get the string describing this display connection */
692
if (!orig) return NULL;
694
/* create a working copy */
696
display_name = strdup(orig);
697
if (!display_name) return NULL;
699
/* skip past the host */
701
colon = strchr(display_name, ':');
702
if (!colon) return NULL;
704
/* if no host is specified, prepend the local hostname */
706
/* XXX should we try to catch "localhost"? */
708
if (display_name == colon) {
709
if (uname(&uname_buf) == 0) {
710
len = strlen(display_name) + strlen(uname_buf.nodename) + 1;
712
snprintf(tmp, len, "%s%s", uname_buf.nodename, display_name);
715
colon = strchr(display_name, ':');
716
if (!colon) return NULL;
721
* if the screen parameter is -1, then extract the screen number,
722
* either from the string or default to 0
726
dot = strchr(colon, '.');
728
screen = atoi(dot + 1);
735
* find the separation between the display and the screen; if we
736
* find it, then truncate the string before the screen, so that we
737
* can append the correct screen number.
740
dot = strchr(colon, '.');
741
if (dot) *dot = '\0';
743
len = strlen(display_name) + 8;
744
screen_name = malloc(len);
745
snprintf(screen_name, len, "%s.%d", display_name, screen);
749
return (screen_name);
755
* allocate an output string, and copy the input string to the output
756
* string, omitting whitespace
759
char *remove_spaces(const char *o)
764
if (!o) return (NULL);
768
no_spaces = (char *) malloc (len+1);
772
if (!isspace (*o)) { *m++ = *o; }
777
len = m - no_spaces + 1;
778
no_spaces = (char *) (realloc (no_spaces, len));
782
} /* remove_spaces() */
786
/**************************************************************************/
791
* nv_strtok () - returns a dynamically allocated array of strings,
792
* which are the separate segments of the passed in string, divided by
793
* the character indicated. The passed-by-reference argument num will
794
* hold the number of segments found. When you are done with the
795
* array of strings, it is best to call nvFreeStrToks () to free the
796
* memory allocated here.
799
static char **nv_strtok(char *s, char c, int *n)
802
char **delims, **tokens, *m;
804
count = count_number_of_chars(s, c);
807
* allocate and set pointers to each division (each instance of the
808
* dividing character, and the terminating NULL of the string)
811
delims = (char **) malloc((count+1) * sizeof(char *));
813
for (i = 0; i < count; i++) {
818
delims[count] = (char *) strchr(s, '\0');
821
* so now, we have pointers to each deliminator; copy what's in between
822
* the divisions (the tokens) into the dynamic array of strings
825
tokens = (char **) malloc((count+1) * sizeof(char *));
827
tokens[0] = nv_strndup(s, len);
829
for (i = 1; i < count+1; i++) {
830
len = delims[i] - delims[i-1];
831
tokens[i] = nv_strndup(delims[i-1]+1, len-1);
844
* nv_free_strtoks() - free an array of arrays, such as what is
845
* allocated and returned by nv_strtok()
848
static void nv_free_strtoks(char **s, int n)
851
for (i = 0; i < n; i++) free(s[i]);
854
} /* nv_free_strtoks() */
859
* character to integer conversion
862
static int ctoi(const char c)
871
* count_number_of_chars() - return the number of times the
872
* character d appears in the string
875
static int count_number_of_chars(char *o, char d)
884
} /* count_number_of_chars() */
889
* nv_strndup() - this function takes a pointer to a string and a
890
* length n, mallocs a new string of n+1, copies the first n chars
891
* from the original string into the new, and null terminates the new
892
* string. The caller should free the string.
895
static char *nv_strndup(char *s, int n)
897
char *m = (char *) malloc(n+1);