+const char *PRVM_GetString(int num)
+{
+ if (num >= 0 && num < pr_stringssize)
+ return pr_strings + num;
+ else if (num < 0 && num >= -pr_numknownstrings)
+ {
+ num = -1 - num;
+ if (!pr_knownstrings[num])
+ Host_Error("PRVM_GetString: attempt to get string that is already freed\n");
+ return pr_knownstrings[num];
+ }
+ else
+ {
+ Host_Error("PRVM_GetString: invalid string offset %i\n", num);
+ return "";
+ }
+}
+
+int PR_SetQCString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ return s - pr_strings;
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_knownstrings[i] == s)
+ return -1 - i;
+ Host_Error("PR_SetQCString: unknown string\n");
+ return -1 - i;
+}
+
+int PRVM_SetEngineString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ Host_Error("PRVM_SetEngineString: s in pr_strings area\n");
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_knownstrings[i] == s)
+ return -1 - i;
+ // new unknown engine string
+ if (developer.integer >= 3)
+ Con_Printf("new engine string %p\n", s);
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (!pr_knownstrings[i])
+ break;
+ if (i >= pr_numknownstrings)
+ {
+ if (i >= pr_maxknownstrings)
+ {
+ const char **oldstrings = pr_knownstrings;
+ pr_maxknownstrings += 128;
+ pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+ if (pr_numknownstrings)
+ memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+ }
+ pr_numknownstrings++;
+ }
+ pr_knownstrings[i] = s;
+ return -1 - i;
+}
+
+char *PR_AllocString(int bufferlength)
+{
+ int i;
+ if (!bufferlength)
+ return 0;
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (!pr_knownstrings[i])
+ break;
+ if (i >= pr_numknownstrings)
+ {
+ if (i >= pr_maxknownstrings)
+ {
+ const char **oldstrings = pr_knownstrings;
+ pr_maxknownstrings += 128;
+ pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+ if (pr_numknownstrings)
+ memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+ }
+ pr_numknownstrings++;
+ }
+ return (char *)(pr_knownstrings[i] = PR_Alloc(bufferlength));
+}
+
+void PR_FreeString(char *s)
+{
+ int i;
+ if (!s)
+ Host_Error("PR_FreeString: attempt to free a NULL string\n");
+ if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+ Host_Error("PR_FreeString: attempt to free a constant string\n");
+ for (i = 0;i < pr_numknownstrings;i++)
+ if (pr_knownstrings[i] == s)
+ break;
+ if (i == pr_numknownstrings)
+ Host_Error("PR_FreeString: attempt to free a non-existent or already freed string\n");
+ PR_Free((char *)pr_knownstrings[i]);
+ pr_knownstrings[i] = NULL;
+}
+