+
+/* Formats the nickname of the client specified by the `client_entry'.
+ If the format is specified by the application this will format the
+ nickname and replace the old nickname in the client entry. If the
+ format string is not specified then this function has no effect. */
+
+void silc_client_nickname_format(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ char *cp;
+ char *newnick = NULL;
+ int i, off = 0, len;
+ SilcClientEntry *clients;
+ uint32 clients_count;
+
+ if (!client->params->nickname_format[0])
+ return;
+
+ if (!client_entry->nickname)
+ return;
+
+ /* Get all clients with same nickname. Do not perform the formatting
+ if there aren't any clients with same nickname unless the application
+ is forcing us to do so. */
+ clients = silc_client_get_clients_local(client, conn,
+ client_entry->nickname, NULL,
+ &clients_count);
+ if (!clients && !client->params->nickname_force_format)
+ return;
+
+ cp = client->params->nickname_format;
+ while (*cp) {
+ if (*cp == '%') {
+ cp++;
+ continue;
+ }
+
+ switch(*cp) {
+ case 'n':
+ /* Nickname */
+ if (!client_entry->nickname)
+ break;
+ len = strlen(client_entry->nickname);
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], client_entry->nickname, len);
+ off += len;
+ break;
+ case 'h':
+ /* Stripped hostname */
+ if (!client_entry->hostname)
+ break;
+ len = strcspn(client_entry->hostname, ".");
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], client_entry->hostname, len);
+ off += len;
+ break;
+ case 'H':
+ /* Full hostname */
+ if (!client_entry->hostname)
+ break;
+ len = strlen(client_entry->hostname);
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], client_entry->hostname, len);
+ off += len;
+ break;
+ case 's':
+ /* Stripped server name */
+ if (!client_entry->server)
+ break;
+ len = strcspn(client_entry->server, ".");
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], client_entry->server, len);
+ off += len;
+ break;
+ case 'S':
+ /* Full server name */
+ if (!client_entry->server)
+ break;
+ len = strlen(client_entry->server);
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], client_entry->server, len);
+ off += len;
+ break;
+ case 'a':
+ /* Ascending number */
+ {
+ char tmp[6];
+ int num, max = 1;
+
+ if (clients_count == 1)
+ break;
+
+ for (i = 0; i < clients_count; i++) {
+ if (strncmp(clients[i]->nickname, newnick, off))
+ continue;
+ if (strlen(clients[i]->nickname) <= off)
+ continue;
+ num = atoi(&clients[i]->nickname[off]);
+ if (num > max)
+ max = num;
+ }
+
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp) - 1, "%d", ++max);
+ len = strlen(tmp);
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len));
+ memcpy(&newnick[off], tmp, len);
+ off += len;
+ }
+ break;
+ default:
+ /* Some other character in the string */
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + 1));
+ memcpy(&newnick[off], cp, 1);
+ off++;
+ break;
+ }
+
+ cp++;
+ }
+
+ newnick = silc_realloc(newnick, sizeof(*newnick) * (off + 1));
+ newnick[off] = 0;
+
+ silc_free(client_entry->nickname);
+ client_entry->nickname = newnick;
+ silc_free(clients);
+}