XLib Event Loop - My code entry point??

This is a discussion on XLib Event Loop - My code entry point?? within the Linux Programming forums, part of the Platform Specific Boards category; I'm working on a terminal/monitoring program that displays serial input stream using standard lib fopen() in a window. I used ...

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    5

    XLib Event Loop - My code entry point??

    I'm working on a terminal/monitoring program that displays serial input stream using standard lib fopen() in a window. I used a file viewing program as the basis for my Xlib program. I have modifed it get its input from the serial port, instead of a file. Everything works fine, but now I need read lines of serial I/O continiously into a circular buffer and output it directly to a Region of the window until told to stop. It really nothing more than a terminal window.

    For this discussion, I'm just focused on how do I keep reading serial input while the processing has moved into the event loop. The function call display_lines() does all of the work copying and clearing regions, and scrolling lines of data up or down in the window.

    if (theEvent.xexpose.count == 0) display_lines();
    break;

    Q: Do I need to fork() a child process? If so, and where.

    I've been looking for code eamples, but haven't found any so far. I looked at xterm source, but it was to complicated to follow.



    Hope someone can guide me in the right direction. This is pure XLib programming. I will be glad to post code and expand on this more if needed.


    jw

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,494
    Yes, more code would help.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Oct 2012
    Posts
    5

    Xlib Event Loop - My code snippet

    Okay, I give up on code tagging. I don't know what the deal is...? I had everything laid out correctly in this message and it won't let me submit.

    Code:
    My code....
    It should be that simple... Oh well, just see the file.
    Attached Files Attached Files

  4. #4
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    So, why did that work? I guess the code tag don't like my code!!

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    2,708
    Here is the code placed inside code tags.

    Code:
    /*-------------------------------------------------------------*/
    /*  File: xjwmon_2-1.c
     *
     *  Program to view serial output from /dev/ttyS? port.  
     */
     /*-------------------------------------------------------------*/
    
    #include <stdio.h>
    #include <string.h>
    
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <X11/keysym.h>
    
    #include "xwins.h"
    #include "app_glob.c"
    
    #define LEFT_MARGIN  4    /* Leave a 4-pixel margin */
    
    /* Maximum length of string generated by a keypress */
    
    #define MAX_MAPPING 10   
    
    /* Menu styles */
    #define MENUBAR_STYLE  0
    #define PULLDOWN_STYLE  1
    
    #define SCROLL_UP    0
    #define SCROLL_DOWN  1
    
    #define MAXCHARS   250     /* Maximum length of a line    */
    
    typedef struct D_LINE      /* Holds info on each line     */
    {
        struct D_LINE *prev;   /* Pointer to previous line    */
        struct D_LINE *next;   /* Pointer to next line        */
        char          *line;   /* Null-terminated line        */
        short         length;  /* Number of characters in line*/
        short         lbearing;/* Left and right edges of     */
        short         rbearing;/* rectangle covered by line   */
        short         height;  /* Height of text string       */
    } D_LINE;
    
    typedef struct D_LBUF      /* Info on entire buffer       */
    {
        D_LINE        *lines;  /* First line in buffer        */
        D_LINE        *lstart; /* First line in window        */
        GC            gc;      /* GC used to display text     */
        Region        rexp;    /* Current exposed region      */
        XFontStruct   *fstruct;/* Info on current font        */
        int           font;    /* Currently selected font     */
        int           weight;  /* weight and                  */
        int           size;    /* size                        */
        unsigned      dwidth;  /* Width of text display area  */
        unsigned      dheight; /* Height of text display area */
        long          count;   /* How many lines in buffer    */
    } D_LBUF;
    
    static D_LBUF fbuf = { NULL,NULL, None, None, None, 0, 0, 0,
                           0, 0, 0};
    
    static int zero=0, one=1, two=2, three=3, four=4;
    
    static  GC     invertGC;   /* GC used for highlighting    */
    static  int    PullDownOn = 0,
                   full_update = 0;
    static  Window pulldown_id;
    static  unsigned quit_width, quit_height;
    
    /* Information necessary to construct X11R3 font names    */
    static char *fontname[] =
    {
      "courier", "helvetica", "new century schoolbook", "times"
    };
    static char *weight[] = { "medium", "bold" };
    static char *size[] = {"100", "120", "140", "180", "240"};
    
    char *quit_label = "Quit";
    
    /* File to be opened */
    char *port_name;
    static FILE *fp;
    
    /* Function prototypes */
    
    void initapp(/* int, char **, int, int, unsigned, unsigned */);
    static int  disp_menu(/* caddr_t */);
    static int  quit_action(/* caddr_t */);
    static void process_event(); 
    static void hilite_button(/* XWIN * */);
    
    static int  font_select(/* caddr_t */);
    static int  wt_select(/* caddr_t */);
    static int  size_select(/* caddr_t */);
    
    static void open_port(/* char *portname */);
    static void apply_font();
    static void read_lines(); /* read input */
    static void display_lines();
    static void scroll_lines(/* int direction, int numlines */);
    
    /* Windows in the application */
    
    Window dWin;
    XWIN   *menubar, *PullDown[3];
    
    /*-------------------------------------------------------------*/
    main(argc, argv)
    int argc;
    char **argv;
    {
        XWIN     *QuitButton, *which_xwin;
        XGCValues xgcv;
        int      i, yp, xp1, xp2;
    /*    char     buf[MAXCHARS] */;
    /*    FILE     *fp; */ 
    
        xwin_init();
            
        initapp(argc, argv, 20, 20, 500, 400);
    
    /* Get file name from command line */    
        for (i = 1; i < argc; i += 2) 
        {
            if(strcmp("-port", argv[i]) == 0)
            {
                port_name = argv[i+1]; 
                break;
            }
        }
        if(i >= argc)
        {
            fprintf(stderr, "Need: xjwmon -port </dev/ttyS?>\n");
            exit(1);
        }
    
    /* Create the "Quit" button */
        quit_width = XTextWidth(theFontStruct, quit_label, 
                                strlen(quit_label)) + 4;
        quit_height = theFontStruct->max_bounds.ascent + 
                      theFontStruct->max_bounds.descent + 4;
    
        QuitButton = MakeXButton(2, 3, quit_width, quit_height,
                                 1, theFGpix, theBGpix, theMain, 
                                 quit_label, quit_action, NULL);
    
    /* Create a menu bar */
        menubar = MakeXMenu(quit_width+16, 1, 1, theFGpix, theBGpix, 
                      theMain, MENUBAR_STYLE,
                      "Font",   disp_menu, (caddr_t)&zero,
                      "Weight", disp_menu, (caddr_t)&one,
                      "Size",   disp_menu, (caddr_t)&two,
                      NULL);
    
        yp = quit_height + 10;
    
        xp1 = quit_width+16 + XTextWidth(theFontStruct, 
                         "Font", strlen("Font")) + 8;
                                
        xp2 = xp1 + XTextWidth(theFontStruct, 
                         "Weight", strlen("Weight")) + 8;
    
    /* Create the pull-down menus */
        PullDown[0] = MakeXMenu(0, yp, 1, theFGpix, theBGpix, 
                      theMain, PULLDOWN_STYLE,
                      "Courier",     font_select, (caddr_t)&zero,
                      "Helvetica",   font_select, (caddr_t)&one,
                      "New Century Schoolbook", 
                                     font_select, (caddr_t)&two,
                      "Times",       font_select, (caddr_t)&three,
                      NULL);
    
        PullDown[1] = MakeXMenu(xp1, yp, 1, theFGpix, theBGpix, 
                      theMain, PULLDOWN_STYLE,
                      "Medium",  wt_select, (caddr_t)&zero,
                      "Bold",    wt_select, (caddr_t)&one,
                      NULL);
    
        PullDown[2] = MakeXMenu(xp2, yp, 1, theFGpix, theBGpix, 
                      theMain, PULLDOWN_STYLE,
                      " 10pt",       size_select, (caddr_t)&zero,
                      " 12pt",       size_select, (caddr_t)&one,
                      " 14pt",       size_select, (caddr_t)&two,
                      " 18pt",       size_select, (caddr_t)&three,
                      " 24pt",       size_select, (caddr_t)&four,
                      NULL);
    
    /* Set up a GC to display text */
    
        fbuf.gc = XCreateGC(theDisplay, theMain, 0, 0);
        XCopyGC(theDisplay, theGC, GCForeground | GCBackground |
                GCFont, fbuf.gc);
                
    /* Set up a GC to hilight the buttons */
    
        invertGC = XCreateGC(theDisplay, theMain, 0, 0);
        XCopyGC(theDisplay, theGC, GCForeground | GCBackground,
                invertGC);
        XSetFunction(theDisplay, invertGC, GXinvert);
        XSetPlaneMask(theDisplay, invertGC, theFGpix^theBGpix);
    
    /* Add ButtonRelease to the event selection of the main
     * window so that we can detect when the user releases
     * the button without selecting any menu item.
     */
        AddNewEvent(theMain, ButtonReleaseMask|StructureNotifyMask);
        
    /* Create and map a window that serves as the file display area */
        dWin = XCreateSimpleWindow(theDisplay, theMain, 1,
               quit_height+8, 500, 400, 1, theFGpix, theBGpix);
    
        XSelectInput(theDisplay, dWin, ExposureMask |
                     ButtonPressMask | OwnerGrabButtonMask|
                     ButtonReleaseMask | StructureNotifyMask | 
                     KeyPressMask);
    
        XMapRaised(theDisplay, dWin);
            
    /* JW's Notes:
     *
     *   
     */
    
     /* open the serial port using standard I/O. */
     
        open_port(port_name); 
    	 read_lines(); 
        		fbuf.lstart = fbuf.lines;  /* loads .lstart with the first line in the buffer. */
    			printf("assign fbuf.lstart = fbuf.lines....\n\n");
    
       	 apply_font();  
    	/* printf("apply_font() completed....\n\n"); */
    
        	fbuf.rexp = XCreateRegion();
    	printf("initialize fbuf.rexp = XCreateRegion() complete....\n\n");
    
    /* Event handling loop--keep processing events until done */
    
    printf("start processing events in event loop....\n\n");
    
        while (!AppDone)
            	process_event();
    
    /* Close connection to display and exit */
    
        XCloseDisplay(theDisplay);
    	 fclose(fp);   
        exit(0);
    }
    
    /*-------------------------------------------------------------*/
    /*  p r o c e s s _ e v e n t 
     *  
     *  Retrieve an event and process it...
     */
    static void process_event()
    {
        XWIN     *which_xwin;
    
    /* Get the next event from Xlib */
        XNextEvent(theDisplay, &theEvent);
    
    /* If main window is resized, we must resize dWin */
        if(theEvent.xany.window == theMain &&
           theEvent.type == ConfigureNotify)
        {
            XResizeWindow(theDisplay, dWin, theEvent.xconfigure.width,
                        theEvent.xconfigure.height - quit_height - 8);
        }
    
    /* Handle events for the dWin, the text display window */
        if(theEvent.xany.window == dWin)
        {
            switch (theEvent.type)
            {
                case Expose:
                {            	
    /* Accumulate exposed areas in a region */
                    XRectangle r;
                    r.x = theEvent.xexpose.x;
                    r.y = theEvent.xexpose.y;
                    r.width = theEvent.xexpose.width;
                    r.height = theEvent.xexpose.height;
    
                    XUnionRectWithRegion(&r, fbuf.rexp, fbuf.rexp);
                    if(fbuf.dwidth == 0 || fbuf.dheight == 0)
                    {
                        Window rid;
                        int junk;
    
    	    /* Get dimensions of this window */
                        XGetGeometry(theDisplay, theMain, &rid, &junk, 
                 &junk, &fbuf.dwidth, &fbuf.dheight, &junk, &junk);
                        fbuf.dheight -= (quit_height+8);
                    }
    
                    if(theEvent.xexpose.count == 0) display_lines(); 
                     break; 
    
    	    }/* close brace for case Expose: */
    
                case KeyPress:
                    {
                        char    xlat[MAX_MAPPING];
                        KeySym  key;
                        int     count;
    	    /* Translate keycode into keysym and string */
                        count = XLookupString(&theEvent, xlat, 
                                      MAX_MAPPING, &key, None);
    
    	    /* Up and Down arrows */
                        if(key == XK_Up)
                            scroll_lines(SCROLL_DOWN, 1);
    
                        if(key == XK_Down)
                            scroll_lines(SCROLL_UP, 1);
    
    /* Is it Ctrl-D or Ctrl-U? */
                        if(theEvent.xkey.state & ControlMask)
                        {
                            if(key == XK_l)
    /* Refresh display */       XClearArea(theDisplay, dWin, 
                                           0,0,0,0,True);
    			printf("screen refreshed...\n");
                            if(key == XK_u)
                                scroll_lines(SCROLL_DOWN, 
                                   fbuf.dheight/fbuf.lstart->height-1);
                            if(key == XK_d)
                                scroll_lines(SCROLL_UP, 
                                   fbuf.dheight/fbuf.lstart->height-1);
    
                        } /* close brace for if(theEvent.xkey.state & ControlMask) */
                        
                    } /* close brace for case: KeyPress */
                    break;
    
                case ConfigureNotify:
                    fbuf.dwidth = theEvent.xconfigure.width;
                    fbuf.dheight = theEvent.xconfigure.height;
                    XClearArea(theEvent.xany.display, dWin,
                           0, 0, 0, 0, True);
                break;
            } /* close brace for switch() */
    
        } /* close brace for if(theEvent.xany.window == dWin) */
    
    /************** Process events for other windows  *************/
    /* Next, retrieve the XWIN data from Xlib using the 
     * context manager routine XFindContext
     */
    
        if(XFindContext(theDisplay, theEvent.xany.window,
               xwin_context, (caddr_t *) &which_xwin) == 0)
        {
    /* Call the event handler of this XWIN structure */
            if (*(which_xwin->event_handler) != NULL)
                (*(which_xwin->event_handler))(which_xwin);
        }
    
    /* Handle EnterNotify and LeaveNotify events for the buttons */
        if(theEvent.type == EnterNotify ||
           theEvent.type == LeaveNotify)
                               hilite_button(which_xwin);
    
         if(PullDownOn && theEvent.type == ButtonRelease) 
            PullDownOn = 0;
    
    }
    /*-------------------------------------------------------------*/
    static int disp_menu(data)
    caddr_t data;
    {
        XWIN   *which_xwin;
        int    menu_number;
        
    /* Display the PullDown menu and process events until a
     * choice is made 
     */
        menu_number = * ((int *) data);
        pulldown_id = PullDown[menu_number]->xid;
        XMapRaised(theDisplay, pulldown_id);
        PullDownOn = 1;
    
        while(PullDownOn)
            process_event();
    
    /* Unmap the pull-down menu window */    
        XUnmapWindow(theDisplay, pulldown_id);
    
        return 1;
    }
    /*-------------------------------------------------------------*/
    /*  q u i t _ a c t i o n
     *
     *  This routine is called when a ButtonPress event occurs in
     *  the quit window.
     */
    static int quit_action(data)
    caddr_t data;
    {
    /* Set the done flag */
        AppDone = 1;
        return 1;
    }
    /*-------------------------------------------------------------*/
    /*  h i l i t e _ b u t t o n
     *
     *  Highlight a button window by inverting it
     */
    static void hilite_button(p_xwin)
    XWIN *p_xwin;
    {
        int i, go_on = 0;
    /* Check if window's parent is one of the pull-down menus */
        for(i = 0; i < 3; i++)
        {
            if(p_xwin->parent == PullDown[i]->xid) 
            {
                go_on = 1;
                break;
            }
        }
        if (!go_on) return;
        
    /* Invert a rectangle large enough so that the button window
     * gets highlighted
     */
        XFillRectangle(theDisplay, p_xwin->xid, invertGC, 
                       0, 0, 1024, 1024);
        XFlush(theDisplay);
    }
    
    /*-------------------------------------------------------------*/
    /*  f o n t _ s e l e c t
     *
     *  Process a font selection
     *
     */
    static int font_select(data)
    caddr_t data;
    {
        int font = *((int *)data);
        PullDownOn = 0;
        if(font != fbuf.font)
        {
            fbuf.font = font;
            apply_font();
    
    /* Clear the display window so that text is displayed again */
            XClearArea(theDisplay, dWin, 0, 0, 0, 0, True);
        }
        return 1;
    }
    
    /*-------------------------------------------------------------*/
    /*  w t _ s e l e c t
     *
     *  Font weight changed.
     *
     */
    static int wt_select(data)
    caddr_t data;
    {
        int weight = *((int *)data);
        PullDownOn = 0;
        if(weight != fbuf.weight)
        {
            fbuf.weight = weight;
            apply_font();
    /* Clear the display window so that text is displayed again */
            XClearArea(theDisplay, dWin, 0, 0, 0, 0, True);
        }
        return 1;
    }
        
    /*-------------------------------------------------------------*/
    /*  s i z e _ s e l e c t
     *
     *  New size font selected
     *
     */
    static int size_select(data)
    caddr_t data;
    {
        int size = *((int *)data);
        PullDownOn = 0;
        if(size != fbuf.size)
        {
            fbuf.size = size;
            apply_font();
    
    /* Clear the display window so that text is displayed again */
            XClearArea(theDisplay, dWin, 0, 0, 0, 0, True);
        }
        return 1;
    }
    /*-------------------------------------------------------------*/
    /*  o p e n  s e r i a l  p o r t   
     *
     *  JW's Notes:
     *  1) Open the serial port instead of a file using C libaray
     *  standard I/O.
     */
    static void open_port(portname)
    char *portname;
    {
    
    /* Open the serial port in "r" (read mode) using standard I/O. */
    
        if((fp = fopen(portname, "r")) == NULL)
        {
            fprintf(stderr, "Cannot open: %s\n", portname);
            exit(1);
        }
    }
    
    /*-------------------------------------------------------------*/
    /*  r e a d  s e r i a l  i n p u t   
     *
     *  JW's Notes:
     */
    
    static void read_lines()
    {
        D_LINE *p_l = NULL, *p_l_prev = NULL; 
        char   buf[MAXCHARS];  
    
    /* Read each line and store in linked list of D_LINE structs  */
    	while(((fgets(buf, MAXCHARS, fp)) != NULL) && fbuf.count <= 10)  
    	{
            if((p_l = (D_LINE *) calloc(1, sizeof(D_LINE))) != NULL)
            {
                if(fbuf.lines == NULL)
                {
                    fbuf.lines = p_l;
    		printf("read the first line fbuf.lines...\n\n");
                }
                else
                {
                    p_l_prev->next = p_l;
                    p_l->prev = p_l_prev;
    		printf("read additional lines... p_l_prev-> = p_l\n\n");
                }
            }
            else
            {
    /* Allocation failed...*/
                fprintf(stderr, "Failed to allocate memory for\
    line data structure...\n");
                exit(1);
            }
            p_l->length = strlen(buf) - 1; /* Exclude newline */
            buf[p_l->length] = '\0';
            if((p_l->line = malloc(p_l->length+1)) == NULL)
            {
                fprintf(stderr, "Failed to allocate memory for\
    line:\n%s\n", buf);
                exit(1);
            }
            strcpy(p_l->line, buf);
            p_l_prev = p_l;
            fbuf.count++; 
    	printf("This is line %d\n", fbuf.count);
    
    } /* end of while loop */
    
    }
    
    /*-------------------------------------------------------------*/
    /*  a p p l y _ f o n t
     *
     *  Set up a new font for use. Also compute screen areas 
     *  occupied by each line.
     */
    static void apply_font()
    {
        D_LINE      *p_l;
        int         dir, ascent, descent;
        char        fname[120];      /* Room for font's name */
        XCharStruct cinfo;
        int         font = fbuf.font, 
                    wt = fbuf.weight,
                    sz = fbuf.size;
    /* Construct font's name */
        sprintf(fname, "*adobe-%s-%s-r*%s*", fontname[font], 
                weight[wt], size[sz]);
    
        printf("Font = %s\n", fname);
    
    /* Free the font, if necessary */
        if(fbuf.fstruct != NULL && fbuf.fstruct != theFontStruct) 
            XFreeFont(theDisplay, fbuf.fstruct);
        
    /* Load the new font */             
        if ((fbuf.fstruct = XLoadQueryFont(theDisplay, fname)) 
            == NULL)
        {
            fprintf(stderr, "%s: display %s cannot load font %s\n",
                theAppName, DisplayString(theDisplay), fname);
    
    /* Set fbuf.fstruct to our default font */
            fbuf.fstruct = theFontStruct;
        }
    
    /* Compute bounding box of each line in the buffer */
        for(p_l = fbuf.lines; p_l != NULL; p_l = p_l->next)
        {
           XTextExtents(fbuf.fstruct, p_l->line, p_l->length,
               &dir, &ascent, &descent, &cinfo);
           p_l->lbearing = cinfo.lbearing;
           p_l->rbearing = cinfo.rbearing;
           p_l->height = ascent + descent;
        }
    
    /* Set the font in the GC */
        XSetFont(theDisplay, fbuf.gc, fbuf.fstruct->fid);
    }
    /*-------------------------------------------------------------*/
    /*  d i s p l a y _ l i n e s
     *
     *  Displays the lines in the text window
     */
    static void display_lines()
    {
        int    xpos = 0;
        int    ypos = 0, width;
        D_LINE *p_l;
    
    /* If a full update is needed, alter the exposed region */
        if(full_update)
        {
            XRectangle r;
            r.x = r.y = 0;
            r.width = fbuf.dwidth;
            r.height = fbuf.dheight;
    
            XUnionRectWithRegion(&r, fbuf.rexp, fbuf.rexp);
            full_update = False;
        }
    
    /* Set the accumulated exposed regions as the clip mask */
        XSetRegion(theDisplay, fbuf.gc, fbuf.rexp);
    
    /* Display the lines starting with the first one. Draw
     * a string ONLY if it falls in the exposed region.
     */
    
        for(p_l = fbuf.lstart; p_l != NULL && ypos < fbuf.dheight;
            p_l = p_l->next)
        {
            xpos = LEFT_MARGIN - p_l->lbearing;
            ypos += p_l->height;
            if(XRectInRegion(fbuf.rexp, xpos, ypos - p_l->height,
                             p_l->lbearing + p_l->rbearing,
                             p_l->height) != RectangleOut)
            {
    /* Yes. String's rectangle is partially in region. Draw it */
                XDrawImageString(theDisplay, dWin, fbuf.gc,
                          xpos, ypos, p_l->line, p_l->length);
            }
        }
        
    /* Destroy current region and create a new "empty" one */
        XDestroyRegion(fbuf.rexp);
        fbuf.rexp = XCreateRegion();
        
    /*  s c r o l l _ l i n e s
     *
     *  Scroll the text display by a specified amount.
     */
    static void scroll_lines(direction, numlines)
    int direction;
    int numlines;
    {
        int i, ysrc, yclr, numpix = 0;
        D_LINE *p_l;
    
    /* Figure out how many pixels to scroll */
    
        switch(direction)
        {
            case SCROLL_UP:
                for(i = 0, p_l = fbuf.lstart; 
                    i < numlines && p_l->next != NULL;
                    i++, p_l = p_l->next) numpix += p_l->height;
                ysrc = numpix;
                yclr = fbuf.dheight - numpix;
                break;
    
            case SCROLL_DOWN:
                for(i = 0, p_l = fbuf.lstart; 
                    i < numlines && p_l->prev != NULL;
                    i++, p_l = p_l->prev) numpix += p_l->height;
                ysrc = 0;
                yclr = 0;
                break;
        }
       if(numpix == 0)
        {        
    /* No need to scroll */
            XBell(theDisplay, 0);
            return;
         }
    /* Adjust first line to display */
        fbuf.lstart = p_l;
        
    /* Copy area */
        XSetClipMask(theDisplay, fbuf.gc, None);
        XCopyArea(theDisplay, dWin, dWin, fbuf.gc,
                  0, ysrc, fbuf.dwidth, fbuf.dheight - numpix,
                  0, numpix - ysrc);
    
    /* Clear new rectangle so that it is redrawn */
    
        XClearArea(theDisplay, dWin, 0, yclr,
                   fbuf.dwidth, numpix, True);
    }
    Jim

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,494
    > if((fp = fopen(portname, "r")) == NULL)
    >...
    > while(((fgets(buf, MAXCHARS, fp)) != NULL) && fbuf.count <= 10)
    I would change these to be open() and if ( read() ... ) (note: use of if, not while)

    By having a file descriptor instead of a FILE*, you can then make use of select.

    With this, your event loop would look something like this.
    Code:
        while (!AppDone) {
            fd_set rd;
            FD_CLR(&rd);
            FD_SET(serialfd,&rd);
            if ( select(serialfd+1,&rd,NULL,NULL,NULL) > 0 ) {
                read_lines();
            }
            process_event();
        }
    It's important that read_lines() performs only a single read() call to extract what data is present. If you make more than one call, then it will almost certainly block.

    A further consequence of using read() as opposed to fgets() is that \n is no longer a delimiter. You will need to deal with line fragments within read_lines().
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    Many thanks! I'll try it out. The original source was using open() to read an entire file into memory. I switched to fopen() for testing and stuck with it. As I remember, I saw something about excessive system calls and performance issues using open() and read(). This was in the HOWTO-serial programming doc (old stuff).

  8. #8
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    Salem,

    Can you explain and "blocking" a little more. Is it a general term in C programming, or is it event programming term? I have read about it many times but I'm not totally clear on when it occurs. I assume it is like a wait state in the event loop. I will certainly read up on it again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-16-2010, 02:05 PM
  2. defining entry point
    By vril in forum C Programming
    Replies: 4
    Last Post: 08-16-2009, 09:27 AM
  3. entry point of OLE DB Provider
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 07-19-2007, 04:15 AM
  4. C# COM entry point
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 07-14-2007, 01:51 AM
  5. What a function entry point?
    By KoolGuy18 in forum C Programming
    Replies: 1
    Last Post: 11-01-2002, 10:29 PM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21