+ BufStr_Shrink(prog, stringbuffer);
+}
+
+/*
+========================
+VM_buf_loadfile
+load a file into string buffer, return 0 or 1
+float buf_loadfile(string filename, float bufhandle) = #535;
+========================
+*/
+void VM_buf_loadfile(prvm_prog_t *prog)
+{
+ size_t alloclen;
+ prvm_stringbuffer_t *stringbuffer;
+ char string[VM_STRINGTEMP_LENGTH];
+ int strindex, c, end;
+ const char *filename;
+ char vabuf[1024];
+ qfile_t *file;
+
+ VM_SAFEPARMCOUNT(2, VM_buf_loadfile);
+
+ // get file
+ filename = PRVM_G_STRING(OFS_PARM0);
+ file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false);
+ if (file == NULL)
+ file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false);
+ if (file == NULL)
+ {
+ if (developer_extra.integer)
+ VM_Warning(prog, "VM_buf_loadfile: failed to open file %s in %s\n", filename, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // get string buffer
+ stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1));
+ if(!stringbuffer)
+ {
+ VM_Warning(prog, "VM_buf_loadfile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // read file (append to the end of buffer)
+ strindex = stringbuffer->num_strings;
+ while(1)
+ {
+ // read line
+ end = 0;
+ for (;;)
+ {
+ c = FS_Getc(file);
+ if (c == '\r' || c == '\n' || c < 0)
+ break;
+ if (end < VM_STRINGTEMP_LENGTH - 1)
+ string[end++] = c;
+ }
+ string[end] = 0;
+ // remove \n following \r
+ if (c == '\r')
+ {
+ c = FS_Getc(file);
+ if (c != '\n')
+ FS_UnGetc(file, (unsigned char)c);
+ }
+ // add and continue
+ if (c >= 0 || end)
+ {
+ BufStr_Expand(prog, stringbuffer, strindex);
+ stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
+ alloclen = strlen(string) + 1;
+ stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
+ memcpy(stringbuffer->strings[strindex], string, alloclen);
+ strindex = stringbuffer->num_strings;
+ }
+ else
+ break;
+ }
+
+ // close file
+ FS_Close(file);
+ PRVM_G_FLOAT(OFS_RETURN) = 1;
+}
+
+/*
+========================
+VM_buf_writefile
+writes stringbuffer to a file, returns 0 or 1
+float buf_writefile(float filehandle, float bufhandle, [, float startpos, float numstrings]) = #468;
+========================
+*/
+
+void VM_buf_writefile(prvm_prog_t *prog)
+{
+ int filenum, strindex, strnum, strlength;
+ prvm_stringbuffer_t *stringbuffer;
+
+ VM_SAFEPARMCOUNTRANGE(2, 4, VM_buf_writefile);
+
+ // get file
+ filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
+ if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
+ {
+ VM_Warning(prog, "VM_buf_writefile: invalid file handle %i used in %s\n", filenum, prog->name);
+ return;
+ }
+ if (prog->openfiles[filenum] == NULL)
+ {
+ VM_Warning(prog, "VM_buf_writefile: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
+ return;
+ }
+
+ // get string buffer
+ stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1));
+ if(!stringbuffer)
+ {
+ VM_Warning(prog, "VM_buf_writefile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // get start and end parms
+ if (prog->argc > 3)
+ {
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM2);
+ strnum = (int)PRVM_G_FLOAT(OFS_PARM3);
+ }
+ else if (prog->argc > 2)
+ {
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM2);
+ strnum = stringbuffer->num_strings - strindex;
+ }
+ else
+ {
+ strindex = 0;
+ strnum = stringbuffer->num_strings;
+ }
+ if (strindex < 0 || strindex >= stringbuffer->num_strings)
+ {
+ VM_Warning(prog, "VM_buf_writefile: wrong start string index %i used in %s\n", strindex, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+ if (strnum < 0)
+ {
+ VM_Warning(prog, "VM_buf_writefile: wrong strings count %i used in %s\n", strnum, prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+ return;
+ }
+
+ // write
+ while(strindex < stringbuffer->num_strings && strnum)
+ {
+ if (stringbuffer->strings[strindex])
+ {
+ if ((strlength = (int)strlen(stringbuffer->strings[strindex])))
+ FS_Write(prog->openfiles[filenum], stringbuffer->strings[strindex], strlength);
+ FS_Write(prog->openfiles[filenum], "\n", 1);
+ }
+ strindex++;
+ strnum--;
+ }
+
+ PRVM_G_FLOAT(OFS_RETURN) = 1;