Baby X postscript widget.

77 views
Skip to first unread message

malcolm...@btinternet.com

unread,
Dec 27, 2014, 6:12:39 AM12/27/14
to xpost-...@googlegroups.com
Baby X is a simple, cross-platform windowing toolkit.


It would be nice to have a postscript widget that would render postscript to the
screen.
The interface is simple, you attach a pointer to a BBX_Panel, and return it.
You create children on the panel, for a basic widget, usually one canvas
that takes up the whole of the panel.

The canvas then exposes an rgba buffer, which you draw upon.

Here's the widget in skeleton (untested).

typedef struct
{
  BABYX *bbx;
  BBX_Panel *pan;
  BBX_Canvas *can;
  char *postscript;
} POSTSCRIPT;

/*
   widget constructor
*/
BBX_Panel *createpswidget(BABYX *bbx, BBX_Panel *parent)
{
   POSTSCRIPT *ps;

   ps = bbx_malloc(sizeof(POSTSCRIPT)): /* bbx_malloc never returns NULL */
   ps->bbx = bbx;
   ps->pan = bbx_panel(bbx, parent, "postscript", layout, ps);
   ps->can = 0;     /* canvas empty because we don't know the size */
   ps->postscript = 0;
   return ps->pan;
}

/* every widget needs a destructor */
void  pswidget_kill(BBX_Panel *obj)
{
    POSTSCRIPT *ps;
    if(obj)
    {
      assert(!strcmp(bbx_panel_gettag(), "postscript"));
      ps = bbx_panel_getptr(obj);
      if(ps)
      {
          bbx_canvas_kill(ps->can);  /* need to destroy children first */
          free(ps->postscript);
      }
      bbx_panel_kill(obj);
     }
}

void pswidget_setscript(BBX_Panel *obj, char *postscript)
{
   POSTSCRIPT *ps = bbx_panel_getptr(obj);
   assert(!strcmp(bbx_panel_gettag(obj), "postscript"));
   
   free(ps->postscript);
   ps->postscript = bbx_strdup(ps->postscript));

   redraw(ps);

/*
   private layout function called when position is set and panel sized
*/
static void layout(void *ptr, int width, int height)
{
   POSTSCRIPT ps = ptr;
   bbx_canvas_kill(ps->can):

   ps->can = bbx_canvas(ps->bbx, ps->pan, width, height, bbx_color("white"));
   bbx_setpos(ps->bbx, ps->can, 0, 0, width, height);

   redraw(ps); 
}

/*
   private draw function
*/
static void redraw(POSTSCRIPT *ps)
{
   unsigned char *rgba;
   int width, height;

   if(!ps->can)
      return;
   rgba = bbx_canvas_rgba(ps->can, &width &height);

   bbx_rectangle(rgba, 0, 0, width, height, bbx_color("white")); 
   drawpostscript(rgba, width, height, ps->postscript):

   bbx_canavas_flush(ps->can);
}

luserdroog

unread,
Dec 27, 2014, 2:07:40 PM12/27/14
to xpost-...@googlegroups.com
Excellent. I think this is a good start that we can build on.
 
A first draft of drawpostscript() would look like this:
 
int drawpostscript(unsigned char *rgba, int width, int height, char *psprog)
{
    Xpost_Context *ctx;
    xpost_init();
 
    if (!(ctx = xpost_create("raster:rgba",
            XPOST_OUTPUT_BUFFERIN,
            rgba,
            XPOST_SHOWPAGE_RETURN,
            1, 1,
            XPOST_USE_SIZE, width, height)))
        return fprintf(stderr, "unable to create interpreter context"), 0;
    xpost_run(ctx, XPOST_INPUT_STRING, psprog);
    xpost_destroy(ctx);
    xpost_quit();
    return 1;
}
 
But it may be inefficient to call create every time.
 

malcolm...@btinternet.com

unread,
Dec 27, 2014, 3:31:36 PM12/27/14
to xpost-...@googlegroups.com
Great.

Priority is to get something up and running, we can worry about efficiency when we have postscript working in the GUI.


How would a real user actually want to use a Postscript widget?


luserdroog

unread,
Dec 28, 2014, 1:25:28 AM12/28/14
to xpost-...@googlegroups.com
A first thought is to have two sections: a text-editor pane,
and a graphics pane. And maybe an "execute" button, or
just clicking on the graphics to execute it.
 
Simpler still would be just the graphics pane, and have a
"edit postscript source..." option in the right-click context-menu.
Which would open a pop-up text editor with Ok and Cancel.
Ok would execute the code.
 
Going more elaborate, it could have the text pane and the
graphics pane, and several other panes for various debugging
and tracing logs. postscript code can produce text output on
stdout which could be captured in another (perhaps read-only)
text pane. It also has a logging system with 4 levels of detail
which could be captured in another pane, perhaps with buttons
to highlight or suppress the various types of log messages.
It can also produce a trace output of all operators that are executed
as another separate output.
 
This last setup could be outfitted with controls for single-stepping,
or executing a line-at-time, or finish iteration of loop, or finish loop,
or finish function. A real debugging console. I suppose it would
need a controllable cursor in the primary text pane.
 
On another note, I need to make an option so xpost does not fill
the buffer with white first, so it can be used for "transparency"
effects.
 

malcolm...@btinternet.com

unread,
Dec 28, 2014, 8:58:45 AM12/28/14
to xpost-...@googlegroups.com
The widget is a separate thing to the application.

The widget client is going to get postscript from somewhere or other, then render
it to the Baby X canvas. We'll probably also want a facility to hang a mouse function
off it so you can have an interactive postscript widget.

As a first application, we can hook a Baby X editbox to enter postscript, and
a "go" button to render it. That will take all of five minutes to set up. A single-stepper
will be more effort, of course.

I tried to compile. Unfortunately the src/lib has too many dependencies for Visual Studio
Express. Some of the them are trivia like M_PI, but others go rather deep. Since
we're not actually using any external devices or data sources, those dependencies
are unnecessary.
Maybe there's an easy way of switching the unneeded dependencies off? 



luserdroog

unread,
Jan 3, 2015, 3:06:00 AM1/3/15
to xpost-...@googlegroups.com
[So, we've discovered that the discussion group here (xpost-discuss) does not process email replies. We're stuck with the google-groups interface, which I did not forsee. If this is particularly unpleasant to everyone, we can migrate the thing somewhere else, if that would be beneficial.]
 
Echoing an email reply from Vincent, re-executing the postscript should not be part of the regular redraw cycle. Unless there are some crazy memory constraints, for which you're willing to pay with a lot of processor time. So a function that wraps up all the xpost calls should be used with much caution.
 
Also the drawpostscript function I posted ill-advisedly uses XPOST_SHOWPAGE_RETURN, which is the wrong semantics for re-executing the same drawing over again. I also erroneously suggested by email to use XPOST_SHOWPAGE_DEFAULT here, which is also wrong. That one is for interactive mode where the user must hit the enter key on the keyboard. The correct choice here is ... (drum roll) ... XPOST_SHOWPAGE_NOPAUSE. This lets the postscript code "fall off the bottom" and perform a normal quit. The context may then be re-used by a new call to xpost_run().
 

vincent.torri

unread,
Jan 3, 2015, 12:07:31 PM1/3/15
to xpost-...@googlegroups.com
Hello

i've just begun the Visual Studio project. I have some problems with the glob port that is in the xpost tree, as it is based specifically on MinGW (gcc + binutils) hence, not trivial to port. I think that there is maybe a better and even simpler solution : using FindFirstFile/FindNextFile directly, instead of relying on a dirent port + a glob code.

What do you think ?

Vincent Torri

PS: attached, a diff of the current modifications of xpost for a build with VS 2010, don't hesitate to comment
xpost_vs.diff

luserdroog

unread,
Jan 3, 2015, 2:45:24 PM1/3/15
to xpost-...@googlegroups.com
The patch looks good to my eye, but it fails to apply to my new clone with either of the two most recent commits.
 
C:\Users\josh\Documents\xpost>type configure.ac.rej
--- configure.ac
+++ configure.ac
@@ -245,7 +245,7 @@
    AC_CHECK_HEADERS([sys/mman.h], [have_mmap="yes"], [have_mmap="no"])
 fi
-AC_CHECK_HEADERS([libgen.h unistd.h signal.h sys/select.h])
+AC_CHECK_HEADERS([libgen.h dirent.h unistd.h signal.h sys/select.h])
 ### Checks for types
 
 

luserdroog

unread,
Jan 3, 2015, 3:03:44 PM1/3/15
to xpost-...@googlegroups.com
So, in Visual Studio I'm doing:
File -> Create New Project from existing code
Then I add the root directory and src/bin and src/lib
Then, 'Console application', right? so it doesn't add lots of crazy extra files?
 
Now I'm waiting as it scans and parses.
 
 

vincent.torri

unread,
Jan 3, 2015, 3:47:24 PM1/3/15
to xpost-...@googlegroups.com
ho, wait, i'll add the solution and projects directly in the tree, upstream. For now, he does not even compile, so...

luserdroog

unread,
Jan 3, 2015, 3:48:15 PM1/3/15
to xpost-...@googlegroups.com
Ok. I see now. Tons and tons of errors and "possible loss of data" warnings on all the casts.
 
But... I did "Exclude from project ..." to
xpost_test_*.[ch]
xpost_suite.[ch]
xpost_dev_xcb.[ch]
 
and then there are far fewer errors. Missing M_PI (as others have noted).
It doesn't like function calls in automatic array initializers. (xpost_operator.c:264)
Same thing in xpost_op_matrix.c:121. No `trunc`.
 
No package meta-variables. and "glob". and src/bin/xpost_main.c and src/bin/xpost_client.c can't find src/lib/xpost.h.
 
But _WIN32 is automatically defined, right? So we can "configure" manually in that code path, right?
 

luserdroog

unread,
Jan 3, 2015, 4:20:54 PM1/3/15
to xpost-...@googlegroups.com
I had no fear that you wouldn't! But I wanted to play with it myself and see what all the errors were. The syntax error in xpost_operator.c(264) has me puzzled.
 
static
Xpost_Check_Stack _check_stack_funcs[] = {
    { _stack_none, 0, { } },
    { _stack_int, 1, { integertype } },
    { _stack_real, 1, { realtype } },
    { _stack_float, 1, { floattype } },
    { _stack_any, 1, { anytype } },
    { _stack_bool_bool, 2, { booleantype, booleantype } },
    { _stack_int_int, 2, { integertype, integertype } },
    { _stack_float_float, 2, { floattype, floattype } },
    { _stack_number_number, 2, { numbertype, numbertype } },
    { _stack_any_any, 2, { anytype, anytype } }
};
 
It doesn't like the nesting of initializers? It seems it could be written flat, by padding out the t[] arrays with 0.
 
 

vincent.torri

unread,
Jan 3, 2015, 4:24:36 PM1/3/15
to xpost-...@googlegroups.com
see my patch, i've solved most of the issues for the library

malcolm...@btinternet.com

unread,
Jan 4, 2015, 6:14:13 AM1/4/15
to xpost-...@googlegroups.com
Baby X has a canvas that caches an rgba buffer. So if a window is exposed or hidden, it doesn't generate a draw event. Redraw is only necessary when the contents of the canvas actually change.
We could create a global engine, and actually I think it might be a good idea to hang a dictionary off Baby X so that users can set arbitrary Baby X globals. But if in reality users are just going to have one large postscript window  then it might be over-engineering. Just hang the engine off the widget.

Modern systems have a lot of memory, but I'm not sure if the Baby X canvas scales up. If users are going to want massive canvases, it might be necessary to dispose of the canvas on hide. That raises a lot of other issues, e.g. what to do if the system runs out of memory due a behind the scenes reallocation.

malcolm...@btinternet.com

unread,
Jan 4, 2015, 6:15:54 AM1/4/15
to xpost-...@googlegroups.com
I've got a file glibber for Windows in Baby X.
It's in the FilePicker widget.

I'll rip it out and send it to you.

malcolm...@btinternet.com

unread,
Jan 4, 2015, 2:19:21 PM1/4/15
to xpost-...@googlegroups.com
typedef struct
{
  int folder;
  char *name;
} DIRENTRY;

DIRENTRY *readdirectoryfilt(char *dir, int *N, int hidden, char *filt)
{
  DIRENTRY *answer;
  DIRENTRY *fulldir;
  int j = 0;
  int i;
  
  fulldir = readdirectory(dir, N, hidden);
  if (!fulldir)
  {
 *N = 0;
 return 0;
  }
  answer = bbx_malloc(*N * sizeof(DIRENTRY));
  for(i=0;i<*N;i++)
  {
    if(fulldir[i].folder == 1 || wildcard_match_icase(fulldir[i].name, filt))
    {
      answer[j].folder = fulldir[i].folder;
      answer[j].name = bbx_strdup(fulldir[i].name);
      j++;
    }
  }
  killentries(fulldir, *N);
  *N = j;
  answer = bbx_realloc(answer, j * sizeof(DIRENTRY));
  return answer;
}

#include <assert.h>
DIRENTRY *readdirectory(char *dir, int *N, int hidden)
{
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
TCHAR szDir[MAX_PATH];
size_t length_of_arg;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
int Nch;
int Nread = 0;
int i, j;
char *ptr;
int len;
int count;
DIRENTRY *answer = 0;

if (!strcmp(dir, "\\"))
{
GetLogicalDriveStrings(MAX_PATH, szDir);
i = 0;
while (szDir[i])
{
Nread++;
while (szDir[i])
i++;
i++;
}
answer = bbx_malloc(Nread * sizeof(DIRENTRY));
i = 0;
count = 0;

while (szDir[i])
{
Nch = 0;
j = i;
while (szDir[j])
{
Nch += bbx_utf8_charwidth(szDir[j]);
j++;
}
answer[count].name = bbx_malloc(Nch + 1);
Nch = 0;
j = i;
while (szDir[j])
{
Nch += bbx_utf8_putch(answer[count].name + Nch, szDir[j]);
j++;
}
answer[count].name[Nch] = 0;
answer[count].folder = 1;
answer[count].name[strlen(answer[count].name) - 1] = 0;
i = j+1;
count++;
}
*N = Nread;
return answer;
}


Nch = bbx_utf8_Nchars(dir);
ptr = dir;
for (i = 0; i < Nch; i++)
{
szDir[i] = bbx_utf8_getch(ptr);
ptr += bbx_utf8_skip(ptr);
}
szDir[i] = '\\';
szDir[i + 1] = '*';
szDir[i + 2] = 0;

// Find the first file in the directory.
hFind = FindFirstFile(szDir, &ffd);

if (INVALID_HANDLE_VALUE == hFind)
{
answer = bbx_malloc(sizeof(DIRENTRY));
answer[0].name = bbx_strdup("..");
answer[0].folder = 1;
*N = 1;
return answer;
}

// List all the files in the directory with some info about them.

do
{
if ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) && !hidden)
continue;
answer = bbx_realloc(answer, (Nread + 1) * sizeof(DIRENTRY));
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
answer[Nread].folder = 1;
else
answer[Nread].folder = 0;
len = 0;
for (i = 0; ffd.cFileName[i]; i++)
{
len += bbx_utf8_charwidth(ffd.cFileName[i]);
}
answer[Nread].name = bbx_malloc(len + 1);
ptr = answer[Nread].name;
for (i = 0; ffd.cFileName[i]; i++)
ptr += bbx_utf8_putch(ptr, ffd.cFileName[i]);
*ptr = 0;
Nread++;
} while (FindNextFile(hFind, &ffd) != 0);

dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
return 0;
}

FindClose(hFind);

for (i = 0; i < Nread;i++)
if (!strcmp(answer[i].name, ".."))
break;
if (i == Nread)
{
answer = bbx_realloc(answer, (Nread + 1)*sizeof(DIRENTRY));
answer[Nread].name = bbx_strdup("..");
answer[Nread].folder = 1;
Nread++;
}

*N = Nread;
return answer;
}

/*
DIRENTRY *readdirectory(char *dir, int *N, int hidden)
{
  struct dirent *de=NULL;
  struct stat statbuf;
  DIR *d = NULL;
  DIRENTRY *answer = bbx_malloc(100 * sizeof(DIRENTRY));
  DIRENTRY *temp;
  int capacity =  100;
  int Nread  = 0;
  char path[FILENAME_MAX];

  d=opendir(dir);
  if(d == NULL)
  {
    *N = 0;
    return 0;
  }

  // Loop while not NULL
  while( (de = readdir(d)) )
  {
    makepath(path, FILENAME_MAX, dir, de->d_name);
    if (stat(path, &statbuf) == -1)
       continue;
    if(hidden == 0 && is_hidden(de->d_name))
      continue;
    if(S_ISDIR(statbuf.st_mode))
      answer[Nread].folder = 1;
    else
      answer[Nread].folder = 0;
    answer[Nread].name = bbx_strdup(de->d_name);
    
    Nread++;

    if(Nread == capacity)
    {
      temp = bbx_realloc(answer, (capacity * 2) * sizeof(DIRENTRY));
      if(!temp)
      {
        *N = Nread;
        return answer;
      }
      answer = temp;
      capacity *= 2;
     }
  }

  closedir(d);
  qsort(answer, Nread, sizeof(DIRENTRY), compentries);
  *N = Nread;
  return answer;
}
*/

static int compentries(const void *e1, const void *e2)
{
  const DIRENTRY *d1 = e1;
  const DIRENTRY *d2 = e2;

  if(d1->folder != d2->folder)
    return d2->folder - d1->folder;
  else
    return strcmp(d1->name, d2->name);
}

void killentries(DIRENTRY *entries, int N)
{
  int i;
  if(entries)
  {
    for(i=0;i<N;i++)
      free(entries[i].name);
    free(entries);
  }
}


/*
static int validdirectory(char *dir)
{
   struct stat statbuf;

   if (stat(dir, &statbuf) == -1)
       return 0;
    if(!S_ISDIR(statbuf.st_mode))
      return 0;
 
  return 1;
}
*/


static int is_hidden(char *fname)
{
  int len;
  if(fname && fname[0] == '.')
  {
    if(!strcmp(fname, ".") || !strcmp(fname, ".."))
      return 0;
    return 1;
  }
  if(fname)
  {
    len = strlen(fname);
    if(len > 0 && fname[len-1] == '~')
      return 1;
  }
  return 0;
}


static void makepath(char *out, int N, char *dir, char *sub)
{
  strcpy(out, dir);
  strcat(out, "/");
  strcat(out, sub);
}


static void goupafolder(char *dir)
{
  char *sep;

  sep = strrchr(dir, '\\');
  if(sep && sep != dir)
    *sep = 0;
  if(sep == dir)
    sep[1] = 0;
  if (!sep)
 strcpy(dir, "\\");
}

static void godownafolder(char *dir, char *sub)
{
if (!strcmp(dir, "\\"))
strcpy(dir, sub);
else
{
strcat(dir, "\\");
strcat(dir, sub);
}

static int fileexists(char *path)
{
  struct stat statbuf;

  return stat(path, &statbuf) == -1 ? 0 : 1; 
}

static void trim(char *str)
{
  size_t len;
  size_t i;

  len = strlen(str);
  while(len && isspace( (unsigned char) str[len-1]))
    str[len-- -1] = 0;
  for(i=0;i<len;i++)
    if(!isspace( (unsigned char) str[i]) )
      break;
  if(i > 0)
    memmove(str, str + i, len - i + 1);
   
}
/*
static int is_hidden(char *fname)
{
  int len;
  if(fname && fname[0] == '.')
  {
    if(!strcmp(fname, ".") || !strcmp(fname, ".."))
      return 0;
    return 1;
  }
  if(fname)
  {
    len = strlen(fname);
    if(len > 0 && fname[len-1] == '~')
      return 1;
  }
  return 0;
}
*/



/*
 * This code would not have been possible without the prior work and
 * suggestions of various sourced.  Special thanks to Robey for
 * all his time/help tracking down bugs and his ever-helpful advice.
 *
 * 04/09:  Fixed the "*\*" against "*a" bug (caused an endless loop)
 *
 *   Chris Fuller  (aka Fred1@IRC & Fwitz@IRC)
 *
 * I hereby release this code into the public domain
 *
 */

#include <ctype.h>

#define WILDS '*'  /* matches 0 or more characters (including spaces) */
#define WILDQ '?'  /* matches ecactly one character */

#define NOMATCH 0
#define MATCH (match+sofar)

static int wildcard_match_int(const char *data, const char *mask, int icase)
{
  const char *ma = mask, *na = data, *lsm = 0, *lsn = 0;
  int match = 1;
  int sofar = 0;

  /* null strings should never match */
  if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
    return NOMATCH;
  /* find the end of each string */
  while (*(++mask));
  mask--;
  while (*(++data));
  data--;

  while (data >= na) {
    /* If the mask runs out of chars before the string, fall back on
     * a wildcard or fail. */
    if (mask < ma) {
      if (lsm) {
        data = --lsn;
        mask = lsm;
        if (data < na)
          lsm = 0;
        sofar = 0;
      }
      else
        return NOMATCH;
    }

    switch (*mask) {
    case WILDS:                /* Matches anything */
      do
        mask--;                    /* Zap redundant wilds */
      while ((mask >= ma) && (*mask == WILDS));
      lsm = mask;
      lsn = data;
      match += sofar;
      sofar = 0;                /* Update fallback pos */
      if (mask < ma)
        return MATCH;
      continue;                 /* Next char, please */
    case WILDQ:
      mask--;
      data--;
      continue;                 /* '?' always matches */
    }
    if (icase ? (toupper(*mask) == toupper(*data)) :
(*mask == *data)) {     /* If matching char */
      mask--;
      data--;
      sofar++;                  /* Tally the match */
      continue;                 /* Next char, please */
    }
    if (lsm) {                  /* To to fallback on '*' */
      data = --lsn;
      mask = lsm;
      if (data < na)
        lsm = 0;                /* Rewind to saved pos */
      sofar = 0;
      continue;                 /* Next char, please */
    }
    return NOMATCH;             /* No fallback=No match */
  }
  while ((mask >= ma) && (*mask == WILDS))
    mask--;                        /* Zap leftover %s & *s */
  return (mask >= ma) ? NOMATCH : MATCH;   /* Start of both = match */
}

int wildcard_match(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, 0) != 0;
}

int wildcard_match_icase(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, 1) != 0;
}


Here we go.
I just ripped it out of Baby X.

It's got references to the utf8 handling functions - I can give them to you if you use UTF8 internally,
or you can just replace them with wide char alternatives. utf8_skip and utf8_Nchars thus become
return 1 and wstrlen()

vincent.torri

unread,
Jan 6, 2015, 5:04:18 AM1/6/15
to xpost-...@googlegroups.com
i've written a glob() implementation based on unixem (http://synesis.com.au/software/unixem.html). The license is BSD hence should compatible

i've write it so that it is useful for xpost (that is, the flags and error function must be 0 and NULL resp). The code is around 170 lines

the files are attached

if the solution is sufficiently nice, i can add it in xpost_compat (as the xpost_glob() function) and use it in xpost_op_file.c

ok for that ?

Vincent
glob.c
glob.h

luserdroog

unread,
Jan 6, 2015, 11:27:01 PM1/6/15
to xpost-...@googlegroups.com
Yes, looks good to me. Feel free to commit that.
 
No disrespected intended toward's Malcolm's code. But this version matches the posix interface that the rest of the program expects. http://linux.die.net/man/3/glob
 
Postscript itself doesn't seem to interface well (or at all) with Unicode encodings. I've asked on usenet about it, but nobody really has any idea how it even ought to work. https://groups.google.com/d/topic/comp.lang.postscript/nea_FeBVJvs/discussion
 
And SO doesn't say much either.
 
This is all to say, (unless I'm wrong) I think we can assume ascii-8 here.
 

luserdroog

unread,
Jan 7, 2015, 2:55:16 AM1/7/15
to xpost-...@googlegroups.com
Back to the widget conversation, everybody's seen Don Hopkins' PSIBERspace paper, right? http://www.donhopkins.com/drupal/node/97
 
 

vincent.torri

unread,
Jan 11, 2015, 1:43:42 AM1/11/15
to xpost-...@googlegroups.com
i've read it, indeed, but not understood entirely :p

vincent.torri

unread,
Jan 11, 2015, 1:44:52 AM1/11/15
to xpost-...@googlegroups.com
Malcom

can you try to compile xpost with the VS solution which is in visual_studio/vc9 directory ?

thank you

malcolm...@btinternet.com

unread,
Jan 11, 2015, 2:49:20 AM1/11/15
to xpost-...@googlegroups.com
It won't open the solution.
It will open the vcproj files, and creates its own solution.

But the script which generates config.h isn't being run.
There's also a  file called check.h it can't find.

I'm looking into it a bit more. Can I just undef HASCONFIG_H? 

vincent.torri

unread,
Jan 11, 2015, 2:54:35 AM1/11/15
to xpost-...@googlegroups.com
> It won't open the solution.

which version of Visual Studio do you have ?


> It will open the vcproj files, and creates its own solution.
>
> But the script which generates config.h isn't being run.

there is no script to run to create config.h. There is one in visual_studio/ directory that i have added. What error do you have

> There's also a  file called check.h it can't find.

indeed, it's for unit testing. This file is part of  the check unit testing library : http://check.sourceforge.net/ I'm not sure what the best way to see if this library is available or not

I'm currently installing Visual Studio 2013 Community and I'll check with it

Vincent

malcolm...@btinternet.com

unread,
Jan 11, 2015, 3:15:57 AM1/11/15
to xpost-...@googlegroups.com
I'm using Visual Studio Express 2013 for Desktop.

I can't find the config.h file. Did you add it to git before the commit?

vincent.torri

unread,
Jan 11, 2015, 3:19:56 AM1/11/15
to xpost-...@googlegroups.com
you are right, i have forgotten to add it. Done upstream.

thank you

Vincent

vincent.torri

unread,
Jan 11, 2015, 5:26:21 AM1/11/15
to xpost-...@googlegroups.com
i've renamed vc9 to vc10 (vc9 is visual studio 2008

i've added in vc12 the files for Visual Studio 2013

malcolm...@btinternet.com

unread,
Jan 17, 2015, 7:33:13 AM1/17/15
to xpost-...@googlegroups.com
It compiles now.
It's assert failing.

  fd = mkstemp(l_filenam);

    ret = xpost_memory_file_init(ctx->lo, l_filenam, fd, xpost_interpreter_cid_get_context,
            xpost_interpreter_get_initializing, xpost_interpreter_set_initializing);
    if (!ret)
    {
        close(fd);
        return 0;
    }

mkstemp returns 4, 
ret is zero

the close call assert fails.

  XPOST_LOG_ERR("CreateFileMapping failed (%ld)", GetLastError());
        if (fd != -1) close(fd);

this seems to be the problem. fd is closed twice.


vincent.torri

unread,
Jan 17, 2015, 8:18:16 AM1/17/15
to xpost-...@googlegroups.com
yes, i have also that. It might be because the postscript files are not found. Anyway, it should not assert, even if these files are not found

Btw, do you know a good way to deploy the programs on Windows ? I know NSIS, innosetup and wix. Maybe wix is a good solution (it has visual studio integration, but not on visual studio express). I have downloaded Visual Studio 2013 and it seems that it could work. What do you think ?


malcolm...@btinternet.com

unread,
Jan 17, 2015, 8:43:58 AM1/17/15
to xpost-...@googlegroups.com
I've tracked it down.

fm = CreateFileMapping(h, NULL, PAGE_READWRITE, sz >> 32, sz & 0xffffffff, NULL);
fails. sz is 4096.

fm = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, sz & 0xffffffff, NULL);
succeeds.

a right shift by 32 is undefined behaviour in C.

Unfortuantely it then just gets another error

ERR: c:\users\malcolm\downloads\xpost-7662cf7ece8b\src\lib\xpost_interpreter.c:6
7 _onerror() cannot load $error dict for error: undefinedfilename
OOP in error handler
bort
ERR: c:\users\malcolm\downloads\xpost-7662cf7ece8b\src\lib\xpost_interpreter.c:6
7 _onerror() cannot load $error dict for error: undefined
ERR: c:\users\malcolm\downloads\xpost-7662cf7ece8b\src\lib\xpost_interpreter.c:1
25 xpost_create() undefined error in copyudtosd
ERR: c:\users\malcolm\downloads\xpost-7662cf7ece8b\src\bin\xpost_main.c:400 main


vincent.torri

unread,
Jan 17, 2015, 9:13:41 AM1/17/15
to xpost-...@googlegroups.com
do you compile for 32 bits or 64 bits ? Because it can indeed be the problem if you are targetting 32 bits. I think it's perfectly fine if size_t is 64 bits long. I'll do some tests. Thanks for tracking that error

the next error is the postscript files which are not found (see in data/ all the .ps files. They are needed and must be found)

That's why we need to deploy the program and lib, now, that is : to have an installer and test it.

Vincent

vincent.torri

unread,
Jan 18, 2015, 2:36:52 AM1/18/15
to xpost-...@googlegroups.com
hey

with the attached code, compiled for 64 bits, there is no problem

so, i'll fix the xpost code today
shift.c

luserdroog

unread,
Jan 18, 2015, 7:31:41 PM1/18/15
to xpost-...@googlegroups.com
Yes, installation seems to be necessary, or possibly try using 0 for the is_installed parameter to xpost_create(). That attempts to locate the data files relative to the executable's location, assuming that it's the repository's root.
 
For a quicker path to just get it working, we could use an environment variable.
 
Or for a longer-term solution that could work without a filesystem, I'm thinking about resource-compiling. It may be a good use (/excuse to learn) m4.

luserdroog

unread,
Jan 29, 2015, 2:46:11 AM1/29/15
to
So, the status 11 days later is pretty much the same. It compiles with VS -- 2 versions, right?, I've only checked with VS10. It looks like I have to register to keep using it, but at least I don't have to buy anything. (hate buying stuff, except books).
 
But it does [not] run. Because it can't find the data files. And so we need an installer. I've tried to add a little searching capability, but it's clumsy. And Vincent wasn't impressed, so I didn't try too hard with it. It's mostly a duplication of effort with bin/xpost_pathname.c with impoverished tools (no error mechanism is loaded).
 
So we need an installer. I've browsed the sites for Wix, innosetup, and NSIS, and I can't really choose just by window-shopping, I suppose. Wix means XML, and that kind of makes me cringe, but I can get over it. But if it doesn't work with Express, well that stinks a little.
 
Vincent or Malcolm? further thoughts on which installer to choose?
And does this mean the user (application writer) has to download something else
to do a build, or do we (can we) distribute a complete package (minus compiler of course)?
 
I would like to beef up the library searching enough to run it from the Debug directory.
But then I noticed the overlap with xpost_pathname and I got confused about the best way to go about it. Currently it needs a "backup" error behavior. I've got it set to just call `stop` so the postscript code can use `stopped` to catch it; and it will allow a certain number (currently 5) of these pseudo-errors to happen before it bails-out. I can't decide if doing this is clever or nasty. But it works.
 
Josh
--
droog

vincent.torri

unread,
Jan 29, 2015, 7:33:00 AM1/29/15
to xpost-...@googlegroups.com
Imho, Wix is the way to go (Microsoft itself is using it)

I have installed Visual Studio 2013 Community and I am currently trying to write an MSI. Maybe Community is better that Express.

I'll keep you inform about my success or failure :)

Vincent

vincent.torri

unread,
Jan 29, 2015, 8:56:15 AM1/29/15
to xpost-...@googlegroups.com
Ok, I think that I have succeeded with Visual Studio 2013 Community. I have create a simple C++ program in VS, a Wix project in the same solution, did some slight modifications. The installer installed the binary.

the installer has no GUI by default. But I think that one can find tutorials to add GUI, files, etc...

Vincent
Reply all
Reply to author
Forward
0 new messages