Solved

C/Motif on unix: how to pause app while waiting for user response?

Posted on 2004-09-04
4
484 Views
Last Modified: 2013-12-26
I'm trying to implement a reusable function which asks the user for a response, then performs tasks based on the response.  The app needs to pause and wait until the response is received, but I can't figure out how to do this without locking up the entire app.  In the following example, the Response at line 48 always comes back blank because the run_b routine keeps processing instead of waiting for user_response to complete.  Uncommenting the lines at 46.47 causes the entire app to lockup.  How can I do this?

#define  true            1
#define  false           0

#include <Xm/Xm.h>
#include <Xm/MainW.h>
#include <Xm/PushBG.h>
#include <Xm/MessageB.h>

Widget toplevel;
void question_cb (Widget parent, XtPointer client_data, XtPointer call_data);
void run_cb (Widget widget, XtPointer client_data, XtPointer call_data);
void user_response (char *question);
char Response;
int response_valid;

main (int argc, char *argv[])
{
  XtAppContext app;
  Widget main_window,run_button;

  XtSetLanguageProc (NULL, NULL, NULL);
  toplevel = XtVaAppInitialize (&app, "App", NULL, 0, &argc, argv, NULL,
                        XmNtitle, "Program Do Something Or Other",
                        XmNwidth,     250,
                        XmNheight,    150,
                        NULL);
  main_window = XtVaCreateManagedWidget ("main_window",
                               xmMainWindowWidgetClass, toplevel,
                               NULL);

  run_button = XtVaCreateManagedWidget ("Run", xmPushButtonGadgetClass, main_window,
                              XmNtopAttachment, main_window,
                              NULL);
  XtAddCallback (run_button, XmNactivateCallback, run_cb, NULL);

  XtRealizeWidget (toplevel);

  XtAppMainLoop (app);
}


void run_cb (Widget widget, XtPointer client_data, XtPointer call_data)
{
  /* process a lot of stuff */
 
  user_response ("Do you want to whatever?");
/*  while (!response_valid) {
  }*/
  printf ("Response = '%c'\n",Response);
  if (Response == 'Y') {
    /* do some things */
  } else {
    /* do other things */
  }

  /* continue processing */
}

void user_response (char *question)
{
  Widget dialog;

  response_valid = false;
  dialog = XmCreateQuestionDialog (toplevel, "notice", NULL, 0);
  XtVaSetValues (dialog,
             XmNdialogTitle, XmStringCreateLocalized ("Response"),
             XmNmessageString, XmStringCreateLocalized (question),
             XmNokLabelString, XmStringCreateLocalized ("Yes"),
             XmNcancelLabelString, XmStringCreateLocalized ("No"),
             NULL);
  XtAddCallback (dialog, XmNokCallback, question_cb, NULL);
  XtAddCallback (dialog, XmNcancelCallback, question_cb, NULL);
  XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
  XtManageChild (dialog);
  XtPopup (XtParent (dialog), XtGrabNone);
}


void question_cb (Widget parent, XtPointer client_data, XtPointer call_data)
{
  XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;

  switch (cbs->reason) {
  case XmCR_OK :
    Response = 'Y';
    break;
  case XmCR_CANCEL :
    Response = 'N';
    XtPopdown (XtParent (parent));
    break;
  case XmCR_ACTIVATE :
    break;
  case XmCR_HELP :
    break;
  }
  response_valid = true;
}


0
Comment
Question by:jimdgar
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 45

Expert Comment

by:sunnycoder
ID: 11996229
Not into Motif so no code from my side but there are a couple of possibilities

1. Fork a new process/thread ... let one process/thread block for user while other does the job

2. Use semaphores or conditional variables ... Suppose func A sets something that func B uses and you dont want to block the rest of the app,
Iitialize a semaphore S to 0

func A ()
{
        acquire S if value is 0
        do the processing
        set S to 1 and continue
}

func B ()
{
       acquire S if value is 1
       do the processing
       set S to 0
       continue
}

this will ensure alternation of turns ... You can also use conditional variables if you have more threads in the fray.
0
 
LVL 11

Expert Comment

by:griessh
ID: 11996676
>>  user_response ("Do you want to whatever?");

This line only creates the UI part and sets the callbacks.

You are trying to use the wrong  programming model. X/Motif is an event driven system. Therefore the action takes place in an event handler. The event handler for your response is "question_cb() " and that's where youi have to deal with the response. If you are planning to create a kind of "GUI library" you have to use the callback function as input paramater for "user_response()"

There is no reason for you to wait for the reply, since X is already taking care of that wait. You provided X with a way to handle the reply by installing the event handler "question_cb() ". This function is only called when (!) the user presses one of the buttons.

=====
Werner
0
 

Author Comment

by:jimdgar
ID: 11999508
Conceptually I understand what you're saying but I still can't see how to implement this.  The legacy C code I have is "flow-driven" and depends on getting inputs from the user to make decisions.  These inputs cannot be predetermined, they must happen in realtime.  In a command-line mode it's easy since the entire app simply waits until the user enters a response to an xterm.  Now I want to get the same response from a popup text entry window.

Anyone know of any guidelines on how to do this?  I cannot find similar cases in my Motif manuals or online.
0
 
LVL 11

Accepted Solution

by:
griessh earned 250 total points
ID: 11999816
In a console application every input operation creates its own wait until the user starts typing. X takes that responsibility for you. With "  XtAppMainLoop (app) " you create a loop that will check events for you and your task is to provide handlers for these events.
It is almost impossible to mix these completely different models. If you want to apply a Motif UI to your app you have to make the app work with X/Motif I'm afraid.

>>Now I want to get the same response from a popup text entry window
And that's what you get from X/Motif. You provided a handler for that input event and have to deal with the data. The main() function is there to create widgets and to instantiate the main X event loop. Every action in the system is triggered by some type of event.

=====
Werner
0

Featured Post

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seveā€¦
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question