diff --git a/src/util/guiSubr.c b/src/util/guiSubr.c index 5e76a0983..06dc93ddb 100644 --- a/src/util/guiSubr.c +++ b/src/util/guiSubr.c @@ -29,6 +29,11 @@ * .01 07-30-91 rac installed in SCCS * .02 08-14-91 rac add guiNoticeName; add more documentation * .03 09-06-91 rac add GuiCheckbox..., guiGetNameFromSeln + * .04 10-23-91 rac allow window manager to position command + * frames; add file selector routine; add + * guiInit, guiFileSelect, guiShellCmd; add + * guiTextswXxx; don't specify position for + * frames * * make options * -DXWINDOWS to use xview/X Window System @@ -56,17 +61,22 @@ * void guiCFshowPin_xvo(item) * Panel_item guiCheckbox(label,panel,nItems,pX,pY,pHt,proc,key1,val1,key2,val2) * void guiCheckboxItem(label,checkbox,itemNum,dfltFlag,pX,pY,pHt) +* char *guiFileSelect(pGuiCtx, title, dir, file, dim, callback, pArg) * Frame guiFrame(label, x, y, width, height, ppDisp, pServer) * Frame guiFrameCmd(label, parentFrame, pPanel, resizeProc) * char *guiGetNameFromSeln(pGuiCtx, textSw, headFlag, tailFlag) -* Icon guiIconCreate(frame, iconBits) +* Icon guiIconCreate(frame, iconBits) +* Panel guiInit(pGuiCtx, pArgc, argv, label, x, y, width, height) * Menu guiMenu(proc, key1, val1, key2, val2) * Menu_item guiMenuItem(label, menu, proc, inact, dflt, key1,val1,key2,val2) * Panel_item guiMessage(label, panel, pX, pY, pHt) * void guiNotice(pGuiCtx, msg) * void guiNoticeFile(pGuiCtx, msg, fName) * void guiNoticeName(pGuiCtx, msg, name) +* void guiShellCmd(pGuiCtx, cmdBuf, clientNum, callbackFn, callbackArg) * Panel_item guiTextField(lab,pan,pX,pY,pHt,proc,nStr,nDsp,key1,val1,key2,val2) +* char *guiTextswGets(textsw, pBuf, dim, >pCharNum) +* void guiTextswReset(textsw) * * BUGS * o although they provide some isolation, these routines are still heavily @@ -81,22 +91,22 @@ * #include * * GUI_CTX guiContext; -* -* xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0); -* guiContext.baseFrame = guiFrame("ARR", 100, 100, 0, 0, -* &guiContext.pDisp, &guiContext.server); -* -* panel = (Panel)xv_create(guiContext.baseFrame, PANEL, -* XV_X, 0, XV_Y, 0, PANEL_LAYOUT, PANEL_HORIZONTAL, NULL); +* Panel panel; +* +* panel = guiInit(&guiContext, &argc, argv, "ARR", 100, 100, 0, 0); * *-***************************************************************************/ #include +#include /* for use with notifier */ +#include /* for use with notifier */ +#include /* for use with notifier */ #if defined XWINDOWS # include # include # include +# include # include # include # include @@ -106,6 +116,17 @@ #endif #include + +Notify_value guiCmdRead(), guiCmdSigchld(); +static int callbackNum=-1; +struct callbackStruct { + Notify_client clientNum; + void (*callbackFn)(); + void *callbackArg; + int pipe_io; +}; +static struct callbackStruct callback[100]; + /*+/subr********************************************************************** * NAME guiBrowser - create a browsing text subwindow @@ -265,19 +286,19 @@ Panel panel; /* I panel containing button(s) */ * guiButton("Dismiss", panel, ... * guiCFdismiss_xvo, NULL, GUI_CF, cmdFrame, 0, NULL); * -* menu = guiMenu(..., GUI_PCTX, pCtx...); +* menu = guiMenu(..., GUI_PCTX, pGuiCtx...); * menuItem = guiMenuItem("label", menu, guiCFshow_mi, ..., * GUI_CF, frame...); * * guiButton("Show...", panel, ..., guiCFshow_xvo, ..., -* GUI_PCTX, pCtx, GUI_CF, frame); +* GUI_PCTX, pGuiCtx, GUI_CF, frame); * -* menu = guiMenu(..., GUI_PCTX, pCtx...); +* menu = guiMenu(..., GUI_PCTX, pGuiCtx...); * menuItem = guiMenuItem("label", menu, guiCFshowPin_mi, ..., * GUI_CF, frame...); * * guiButton("Show...", panel, ..., guiCFshowPin_xvo, ..., -* GUI_PCTX, pCtx, GUI_CF, frame); +* GUI_PCTX, pGuiCtx, GUI_CF, frame); * *-*/ void @@ -290,41 +311,31 @@ void guiCFshow_mi(menu, menuItem) Menu menu; Menu_item menuItem; -{ GUI_CTX *pCtx=(GUI_CTX *)xv_get(menu, XV_KEY_DATA, GUI_PCTX); - Rect *mXY; /* mouse position */ +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(menu, XV_KEY_DATA, GUI_PCTX); Frame frame=(Frame)xv_get(menuItem, XV_KEY_DATA, GUI_CF); - mXY = (Rect *)xv_get(xv_get(pCtx->baseFrame, XV_ROOT), WIN_MOUSE_XY); - xv_set(frame, XV_X, mXY->r_left, XV_Y, mXY->r_top, XV_SHOW, TRUE, NULL); + xv_set(frame, XV_SHOW, TRUE, NULL); } void guiCFshowPin_mi(menu, menuItem) Menu menu; Menu_item menuItem; -{ GUI_CTX *pCtx=(GUI_CTX *)xv_get(menu, XV_KEY_DATA, GUI_PCTX); - Rect *mXY; /* mouse position */ +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(menu, XV_KEY_DATA, GUI_PCTX); Frame frame=(Frame)xv_get(menuItem, XV_KEY_DATA, GUI_CF); - mXY = (Rect *)xv_get(xv_get(pCtx->baseFrame, XV_ROOT), WIN_MOUSE_XY); - xv_set(frame, XV_X, mXY->r_left, XV_Y, mXY->r_top, XV_SHOW, TRUE, - FRAME_CMD_PUSHPIN_IN, TRUE, NULL); + xv_set(frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL); } void guiCFshow_xvo(item) Xv_opaque item; -{ GUI_CTX *pCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); - Rect *mXY; /* mouse position */ +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); Frame frame=(Frame)xv_get(item, XV_KEY_DATA, GUI_CF); - mXY = (Rect *)xv_get(xv_get(pCtx->baseFrame, XV_ROOT), WIN_MOUSE_XY); - xv_set(frame, XV_X, mXY->r_left, XV_Y, mXY->r_top, XV_SHOW, TRUE, NULL); + xv_set(frame, XV_SHOW, TRUE, NULL); } void guiCFshowPin_xvo(item) Xv_opaque item; -{ GUI_CTX *pCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); - Rect *mXY; /* mouse position */ +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); Frame frame=(Frame)xv_get(item, XV_KEY_DATA, GUI_CF); - mXY = (Rect *)xv_get(xv_get(pCtx->baseFrame, XV_ROOT), WIN_MOUSE_XY); - xv_set(frame, XV_X, mXY->r_left, XV_Y, mXY->r_top, XV_SHOW, TRUE, - FRAME_CMD_PUSHPIN_IN, TRUE, NULL); + xv_set(frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL); } /*+/subr********************************************************************** @@ -495,6 +506,177 @@ int *pHt; /* O ptr to height used by label, in pixels, or NULL */ xv_set(checkbox, PANEL_VALUE, itemNum, NULL); } + +void guiFileSelCan_pb(); +void guiFileSelCom_pb(); +void guiFileSelLs_pb(); +void guiFileSelLsDone(); +void guiFileSelResize(); + +/*+/subr********************************************************************** +* NAME guiFileSelect - select a file from a group +* +*-*/ +void guiFileSelect(pGuiCtx, title, dir, file, dim, callback, pArg) +GUI_CTX *pGuiCtx; +char *title; +char *dir; +char *file; +int dim; +void (*callback)(); +void *pArg; +{ + Frame frame; + Panel panel; + Panel_item item1, item2; + int x=5, y=5, ht=0; + char message[120]; + + if (pGuiCtx->fsFrame != NULL) + xv_destroy_safe(pGuiCtx->fsFrame); + pGuiCtx->fsCallFn = callback; + pGuiCtx->fsCallArg = pArg; + + frame = guiFrameCmd(title, pGuiCtx->baseFrame, &panel, guiFileSelResize); + xv_set(frame, XV_KEY_DATA, GUI_PCTX, pGuiCtx, NULL); + pGuiCtx->fsFrame = frame; + pGuiCtx->fsDir_PT = guiTextField("Directory:", + panel, &x,&y,&ht, NULL, dim-1, 59, GUI_PCTX, pGuiCtx, 0, NULL); + xv_set(pGuiCtx->fsDir_PT, PANEL_VALUE, dir, NULL); + guiButton("List", panel, &x,&y,&ht, guiFileSelLs_pb, NULL, + GUI_PCTX, pGuiCtx, 0, NULL); + y += ht + 10; x = 5; ht = 0; + pGuiCtx->fsFile_PT = guiTextField("File:", + panel, &x,&y,&ht, NULL, dim-1, 59, GUI_PCTX, pGuiCtx, 0, NULL); + xv_set(pGuiCtx->fsFile_PT, PANEL_VALUE, file, NULL); + y += ht + 10; x = 5; ht = 0; + item1 = guiButton("Cancel", panel, &x,&y,&ht, guiFileSelCan_pb, NULL, + GUI_PCTX, pGuiCtx, 0, NULL); + item2 = guiButton("Commit", panel, &x,&y,&ht, guiFileSelCom_pb, NULL, + GUI_PCTX, pGuiCtx, 0, NULL); + y += ht + 10; x = 5; ht = 0; + pGuiCtx->fsStatus_PM = guiMessage(" ", panel, &x, &y, &ht); + y += ht + 5; x = 5; ht = 0; + + window_fit(panel); + guiButtonCenter(item1, item2, panel); + pGuiCtx->fsTextsw = guiBrowser(frame, panel, 60, 30, NULL); + window_fit(frame); + xv_set(frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL); + sprintf(pGuiCtx->fsLsFile, "/tmp/guiFileSel%d.ls.tmp", getpid()); + unlink(pGuiCtx->fsLsFile); + sprintf(message, "cd %s; ls -l * >%s", dir, pGuiCtx->fsLsFile); + guiShellCmd(pGuiCtx, message, GUI_FILE_SEL_CLIENT, + guiFileSelLsDone, pGuiCtx); + sprintf(message, "processing names in %s", dir); + xv_set(pGuiCtx->fsStatus_PM, PANEL_LABEL_STRING, message, NULL); +} + +/*+/subr********************************************************************** +* NAME guiFileSelCan_pb +* +*-*/ +static void +guiFileSelCan_pb(item) +Panel_item item; +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); + char path[240]; + char *dir, *file; + + xv_set(pGuiCtx->fsFrame, + XV_SHOW, FALSE, FRAME_CMD_PUSHPIN_IN, FALSE, NULL); +} + +/*+/subr********************************************************************** +* NAME guiFileSelCom_pb +* +*-*/ +static void +guiFileSelCom_pb(item) +Panel_item item; +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); + char *pSel, *dir, *file, path[240]; + +/*----------------------------------------------------------------------------- +* if there's selected text, use it for file name. If it's in the +* window listing the files, get the file name from the end of the +* line containing the selected text. +*----------------------------------------------------------------------------*/ + pSel = guiGetNameFromSeln(pGuiCtx, pGuiCtx->fsTextsw, 0, 1); + if (pSel != NULL) + xv_set(pGuiCtx->fsFile_PT, PANEL_VALUE, pSel, NULL); + + dir = (char *)xv_get(pGuiCtx->fsDir_PT, PANEL_VALUE); + file = (char *)xv_get(pGuiCtx->fsFile_PT, PANEL_VALUE); + if (strlen(file) > 0) { + sprintf(path, "%s/%s", dir, file); + pGuiCtx->fsCallFn(pGuiCtx->fsCallArg, path, dir, file); + xv_set(pGuiCtx->fsFrame, + XV_SHOW, FALSE, FRAME_CMD_PUSHPIN_IN, FALSE, NULL); + } + else + guiNotice(pGuiCtx, "file name is blank; select file or use Cancel"); +} + +/*+/subr********************************************************************** +* NAME guiFileSelLs_pb +* +*-*/ +static void +guiFileSelLs_pb(item) +Panel_item item; +{ GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(item, XV_KEY_DATA, GUI_PCTX); + char message[120]; + char *dir=(char *)xv_get(pGuiCtx->fsDir_PT, PANEL_VALUE); + unlink(pGuiCtx->fsLsFile); + sprintf(message, "cd %s; ls -l * >%s", dir, pGuiCtx->fsLsFile); + guiShellCmd(pGuiCtx, message, GUI_FILE_SEL_CLIENT, + guiFileSelLsDone, pGuiCtx); + sprintf(message, "processing names in %s", dir); + xv_set(pGuiCtx->fsStatus_PM, PANEL_LABEL_STRING, message, NULL); +} + +/*+/subr********************************************************************** +* NAME guiFileSelLsDone +* +*-*/ +static void +guiFileSelLsDone(pGuiCtx) +GUI_CTX *pGuiCtx; +{ + char *dir=(char *)xv_get(pGuiCtx->fsDir_PT, PANEL_VALUE); + char message[120]; + xv_set(pGuiCtx->fsTextsw, TEXTSW_FILE, pGuiCtx->fsLsFile, NULL); + unlink(pGuiCtx->fsLsFile); + if ((int)xv_get(pGuiCtx->fsTextsw, TEXTSW_LENGTH) <= 0) + sprintf(message, "there are no files in %s", dir); + else + sprintf(message, "size and modification date are shown"); + xv_set(pGuiCtx->fsStatus_PM, PANEL_LABEL_STRING, message, NULL); +} + +/*+/subr********************************************************************** +* NAME guiFileSelResize +* +*-*/ +static void +guiFileSelResize(window, event, arg) +Xv_Window window; +Event *event; +Notify_arg arg; +{ + Rect rect; + int y; + GUI_CTX *pGuiCtx=(GUI_CTX *)xv_get(window, XV_KEY_DATA, GUI_PCTX); + + if (event_id(event) == WIN_RESIZE) { + rect = *(Rect *)xv_get(pGuiCtx->fsFrame, XV_RECT); + y = (int)xv_get(pGuiCtx->fsTextsw, XV_Y); + xv_set(pGuiCtx->fsTextsw, XV_WIDTH, rect.r_width, + XV_HEIGHT, rect.r_height-y, NULL); + } +} + /*+/subr********************************************************************** * NAME guiFrame - create a base frame * @@ -571,14 +753,14 @@ void (*resizeProc)();/* I function to handle resize, or NULL */ if (resizeProc == NULL) { frame = (Frame)xv_create(parentFrame, FRAME_CMD, FRAME_LABEL, label, - XV_X, 200, XV_Y, 200, XV_SHOW, FALSE, NULL); + XV_SHOW, FALSE, NULL); } else { frame = (Frame)xv_create(parentFrame, FRAME_CMD, FRAME_LABEL, label, FRAME_SHOW_RESIZE_CORNER, TRUE, WIN_EVENT_PROC, resizeProc, WIN_CONSUME_EVENTS, WIN_RESIZE, NULL, - XV_X, 200, XV_Y, 200, XV_SHOW, FALSE, NULL); + XV_SHOW, FALSE, NULL); } if (frame == NULL) { (void)printf("error creating \"%s\" command frame\n", label); @@ -756,6 +938,42 @@ short *iconBits; /* I array of bits for the icon (64 by 64 assuemd) */ } /*+/subr********************************************************************** +* NAME guiInit - initialize the gui routines +* +* DESCRIPTION +* Sets up for gui operations, including: +* o connecting to X11 +* o assimilating X11 options from the command line +* o creating a base frame +* o creating a panel within the base framek +* o initializing the gui context block +* +* RETURNS +* Panel handle +* +*-*/ +Panel +guiInit(pGuiCtx, pArgc, argv, label, x, y, width, height) +GUI_CTX *pGuiCtx; /* I pointer to gui context */ +int *pArgc; /* I pointer to number of command line args */ +char *argv[]; /* I command line args */ +char *label; /* I label for frame and icon */ +int x; /* I x coordinate for frame, in pixels */ +int y; /* I y coordinate for frame, in pixels */ +int width; /* I width of frame, in pixels, or 0 */ +int height; /* I height of frame, in pixels, or 0 */ +{ + + xv_init(XV_INIT_ARGC_PTR_ARGV, pArgc, argv, 0); + pGuiCtx->baseFrame = guiFrame(label, x, y, width, height, + &pGuiCtx->pDisp, &pGuiCtx->server); + pGuiCtx->fsFrame = NULL; + + return (Panel)xv_create(pGuiCtx->baseFrame, PANEL, + XV_X, 0, XV_Y, 0, PANEL_LAYOUT, PANEL_HORIZONTAL, NULL); +} + +/*+/subr********************************************************************** * NAME guiMenu - create a menu * * DESCRIPTION @@ -936,29 +1154,29 @@ int *pHt; /* O ptr to height of message, in pixels, or NULL */ * *-*/ void -guiNotice(pCtx, msg) -GUI_CTX *pCtx; +guiNotice(pGuiCtx, msg) +GUI_CTX *pGuiCtx; /* I pointer to gui context */ char *msg; { - notice_prompt(pCtx->baseFrame, NULL, NOTICE_MESSAGE_STRINGS, msg, NULL, + notice_prompt(pGuiCtx->baseFrame, NULL, NOTICE_MESSAGE_STRINGS, msg, NULL, NOTICE_BUTTON_YES, "Continue", NULL); return; } void -guiNoticeFile(pCtx, msg, fName) -GUI_CTX *pCtx; +guiNoticeFile(pGuiCtx, msg, fName) +GUI_CTX *pGuiCtx; /* I pointer to gui context */ char *msg; char *fName; { perror(fName); - notice_prompt(pCtx->baseFrame, NULL, + notice_prompt(pGuiCtx->baseFrame, NULL, NOTICE_MESSAGE_STRINGS, msg, fName, NULL, NOTICE_BUTTON_YES, "Continue", NULL); return; } void -guiNoticeName(pCtx, msg, name) -GUI_CTX *pCtx; +guiNoticeName(pGuiCtx, msg, name) +GUI_CTX *pGuiCtx; /* I pointer to gui context */ char *msg; char *name; { @@ -969,13 +1187,164 @@ char *name; } else pName = name; - notice_prompt(pCtx->baseFrame, NULL, + notice_prompt(pGuiCtx->baseFrame, NULL, NOTICE_MESSAGE_STRINGS, msg, pName, NULL, NOTICE_BUTTON_YES, "Continue", NULL); return; } /*+/subr********************************************************************** +* NAME guiShellCmd - issue a shell command, cooperating with the notifier +* +* DESCRIPTION +* This routine issues a shell command under the auspices of the +* xview notifier. The command is issued following a fork, with a +* popen call. The critical issue is that the fork results in a +* SIGCHLD signal which the notifier must handle. +* +* This routine (actually guiCmdSigchld) must be customized for each +* application. +* +* This customization handles: +* o doing a file load into sample set text subwindow of the file +* containing a list of file names +* +* RETURNS +* void +* +* BUGS +* o when running under dbx, the child process always results in a +* core dump +* +*-*/ +void +guiShellCmd(pGuiCtx, cmdBuf, clientNum, callbackFn, callbackArg) +GUI_CTX *pGuiCtx; /* I pointer to gui context */ +char *cmdBuf; /* I the command string to give the shell */ +Notify_client clientNum;/* I a unique, arbitrary value to be used by + guiCmdSigchld when the child is done + processing the command */ +void (*callbackFn)();/* I pointer to function for guiCmdSigchld to call */ +void *callbackArg; /* I arg to pass to callbackFn */ +{ + FILE *fp; + int i, pid, cbNum; + char resultBuf[80]; + int pipe_io[2][2]; + + cbNum = callbackNum; + while (cbNum >= 0 && callback[cbNum].clientNum != clientNum) + cbNum--; + if (cbNum < 0) { + if (++cbNum < 100) { + callbackNum = cbNum; + callback[cbNum].clientNum = clientNum; + } + else { + guiNotice(pGuiCtx, "guiShellCmd: overflow of client number table"); + return; + } + } + callback[cbNum].callbackFn = callbackFn; + callback[cbNum].callbackArg = callbackArg; + +/*----------------------------------------------------------------------------- +* blatantly stolen from "XView Programming Manual", Dan Heller, O'Reilly & +* Associates, Inc., July 1990, pp.386-389; section 19.8.2, Reading and +* Writing on Pipes; Example 19-4. The ntfy_pipe.c program +* +* child reads: |<=========== pipe_io[0] <===========| parent writes: +* pipe_io[0][0] pipe_io[0][1] +* +* parent reads: |<=========== pipe_io[1] <===========| child writes: +* pipe_io[1][0] pipe_io[1][1] +*----------------------------------------------------------------------------*/ + + pipe(pipe_io[0]); + pipe(pipe_io[1]); + if ((pid = fork()) == -1) { + perror("error executing shell command"); + close(pipe_io[0][0]); + close(pipe_io[0][1]); + close(pipe_io[1][0]); + close(pipe_io[1][1]); + return; + } + else if (pid == 0) { /* child process */ + dup2(pipe_io[0][0], 0); /* stdin */ + dup2(pipe_io[1][1], 1); /* stdout */ + dup2(pipe_io[1][1], 2); /* stderr */ + for (i=getdtablesize(); i>2; i--) + close(i); /* close the pipe fd's */ + for (i=0; i 0) + fwrite(resultBuf, 1, i, stdout); + _exit(0); + } + close(pipe_io[0][0]); + close(pipe_io[0][1]); + close(pipe_io[1][1]); + callback[cbNum].pipe_io = pipe_io[1][0]; + notify_set_input_func(clientNum, guiCmdRead, pipe_io[1][0]); + notify_set_wait3_func(clientNum, guiCmdSigchld, pid); +} +Notify_value +guiCmdRead(client, fd) +Notify_client client; +int fd; +{ + char buf[80]; + int nBytes, i; + + if (ioctl(fd, FIONREAD, &nBytes) == 0) { + while (nBytes > 0) { + if ((i = read(fd, buf, sizeof(buf))) > 0) { +#if 0 + textsw_insert(textsw, buf, i); + write(1, buf, i); +#endif + nBytes -= i; + } + } + } + return NOTIFY_DONE; +} + +/*/subhead guiCmdSigchld------------------------------------------------------- +* When the child process gets done creating a file, it will die, +* producing SIGCHLD. At that time, call the callback function. +*----------------------------------------------------------------------------*/ +Notify_value +guiCmdSigchld(client, pid, status) +Notify_client client; +int pid; +union wait *status; +{ + Notify_value i=NOTIFY_IGNORED; + int j; + + for (j=0; j<=callbackNum; j++) { + if (client == callback[j].clientNum) { + if (WIFEXITED(*status)) { + notify_set_input_func(client, NOTIFY_FUNC_NULL, + callback[j].pipe_io); + i = NOTIFY_DONE; + } + + if (callback[j].callbackFn != NULL) + callback[j].callbackFn(callback[j].callbackArg); + return i; + } + } + return i; +} + +/*+/subr********************************************************************** * NAME guiTextField - create a text entry field * * DESCRIPTION @@ -1040,3 +1409,68 @@ void *val2; /* I value associated with key */ return item; } + +/*+/subr********************************************************************** +* NAME guiTextswGets - get the next '\n' terminated string from textsw +* +* DESCRIPTION +* Reads the next string from the text subwindow into the caller's +* buffer. Reading stops when a newline is encountered or when the +* caller's buffer is full; the newline IS stored in the buffer. +* The string in the buffer is always null terminated. +* +* The caller must supply the character index (starting with 0) of +* the position in the textsw where reading is to start. On return, +* the caller's index is set to the next available character for +* reading. +* +* RETURNS +* pointer to string, or +* NULL if there are no more characters in text subwindow +* +*-*/ +char * +guiTextswGets(textsw, pBuf, dim, pCharNum) +Textsw textsw; /* I the text subwindow */ +char *pBuf; /* I pointer to buffer to receive string */ +int dim; /* I dimension of buffer */ +int *pCharNum; /* IO index of character to start reading */ +{ + Textsw_index nextPos; + int i; + char *pStr; + + nextPos = (Textsw_index)xv_get(textsw, TEXTSW_CONTENTS, *pCharNum, + pBuf, dim-1); + if (nextPos == *pCharNum) + return NULL; + for (i=0; i= nextPos) { + pBuf[i] = '\0'; + return pBuf; + } + (*pCharNum)++; + if (pBuf[i] == '\n') { + pBuf[i+1] = '\0'; + return pBuf; + } + } + pBuf[i] = '\0'; + return pBuf; +} + +/*+/subr********************************************************************** +* NAME guiTextswReset - reset a text subwindow, discarding its contents +* +* DESCRIPTION +* +* RETURNS +* void +* +*-*/ +void +guiTextswReset(textsw) +Textsw textsw; /* I the text subwindow */ +{ + textsw_reset(textsw, 0, 0); +}