home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / cforms / part03 < prev    next >
Encoding:
Text File  |  1992-05-18  |  29.6 KB  |  1,231 lines

  1. Newsgroups: comp.sources.unix
  2. From: lab@techno.sth.cgl.se (Lars Berntzon)
  3. Subject: v26i058: cforms - forms management front end for curses(3), Part03/03
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: lab@techno.sth.cgl.se (Lars Berntzon)
  8. Posting-Number: Volume 26, Issue 58
  9. Archive-Name: cforms/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 3)."
  18. # Contents:  src/cflib.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Tue May 19 19:14:30 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'src/cflib.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'src/cflib.c'\"
  23. else
  24. echo shar: Extracting \"'src/cflib.c'\" \(27545 characters\)
  25. sed "s/^X//" >'src/cflib.c' <<'END_OF_FILE'
  26. X /*****************************************************************************
  27. X *
  28. X *        C F O R M S . C
  29. X *        ---------------
  30. X *
  31. X * Description:
  32. X *
  33. X * Included functions:
  34. X *
  35. X *        Start/stop functions
  36. X *        --------------------
  37. X *    cforms_init    - Initiate CForms
  38. X *    cforms_end    - Stop CForms
  39. X *
  40. X *        Picture functions
  41. X *        -----------------
  42. X *    pic_call    - Call picture
  43. X *    pic_clear    - Clear all fields for picture
  44. X *    pic_leave    - Leave current picture
  45. X *    picture        - Get picture with name
  46. X *
  47. X *        Field functions
  48. X *        ---------------
  49. X *    field        - Get field with name
  50. X *    fld_isempty    - Check if field is empty
  51. X *    fld_first    - Find first field of picture
  52. X *    fld_next    - Find next field for picture
  53. X *    fld_previous    - Find previous field for picture
  54. X *    fld_left    - Find left field
  55. X *    fld_right    - Find right field
  56. X *    fld_up        - Find field above current
  57. X *    fld_down    - Find field below current
  58. X *    fld_set        - Set value for field
  59. X *    fld_nset    - Set value for field but max n chars
  60. X *    fld_get        - Get value of field
  61. X *    fld_len        - Return length of field
  62. X *    fld_ismodified    - Return true if field has been modified since fld_set
  63. X *    fld_touch    - Make field not modified
  64. X *
  65. X *        General functions
  66. X *        -----------------
  67. X *    message        - Give message (line 24)
  68. X *    strequ        - Compqare two strings, but case insensitive 
  69. X *
  70. X *        Local functions
  71. X *        ---------------
  72. X *    hdl_field    - This is the head function for cforms
  73. X *    getraw        - Get raw key
  74. X *    draw_picture    - Draw picture wiuth fields
  75. X *    check_int    - Checkfunction for integer fields
  76. X *    check_alnum    -     -''-          alphanumeric fields
  77. X *    check_str    -     -''-          string fields
  78. X *    adjust_right    - Adjust string to right
  79. X *    generate_event    - Raise event and call event functions
  80. X *
  81. X * Global variables:
  82. X *    current.picture    - Allways points to current picture (can be NULL)
  83. X *    current.field    - Allways points to current field (can be NULL)
  84. X *
  85. X * Revision:
  86. X *    Ver    Date    By        Reason
  87. X *    ---    ----    --        ------
  88. X *    1.00    900629    Lars Berntzon    Created
  89. X *
  90. X ****************************************************************************/ 
  91. X
  92. X#include "config.h"
  93. X
  94. X#include <stdio.h>
  95. X#include <string.h>
  96. X#include <ctype.h>
  97. X#include <signal.h>
  98. X#include <stdarg.h>
  99. X#ifdef STDLIB_H
  100. X#include <stdlib.h>
  101. X#endif
  102. X#ifdef MALLOC_H
  103. X#include <malloc.h>
  104. X#endif
  105. X
  106. X#include <curses.h>
  107. X#include "cforms.h"
  108. X
  109. X#define KEY_CTRL(c)    (toupper(c) - 'A' + 1)
  110. X
  111. X    /* G l o b a l   v a r i a b l e s */
  112. X
  113. Xstruct current current;        /* Current field and picture        */
  114. X
  115. X    /* L o c a l   v a r i a b l e s */
  116. X
  117. Xstatic int sigcatch(void);
  118. Xstatic int _message(char *fmt, va_list arg);
  119. Xstatic int check_int(int *ch, char *txt, int *pos, int len);
  120. Xstatic int check_alnum(int *ch, char *txt, int *pos, int len);
  121. Xstatic int check_str(int *ch, char *txt, int *pos, int len);
  122. Xstatic int draw_picture(struct picture *pic);
  123. Xstatic int hdl_field(struct field *fld);
  124. Xstatic int adjust_right(char *txt, int len);
  125. X
  126. Xstatic int _leave_picture;
  127. Xstatic int cforms_inited = FALSE;
  128. X
  129. X
  130. X/******************************************************************************
  131. X *
  132. X *        C F O R M S _ I N I T
  133. X *        ---------------------
  134. X * Description:
  135. X *    Initialize cforms. (currently only initscr).
  136. X *
  137. X *****************************************************************************/
  138. Xint
  139. Xcforms_init(void)
  140. X{
  141. X    struct pivture *pp;
  142. X    struct field *fp;
  143. X    int pic, fld;
  144. X
  145. X    cforms_inited = TRUE;
  146. X
  147. X    signal(SIGINT, (SIGNAL_TYPE)sigcatch);
  148. X    
  149. X    if (initscr() == NULL) {
  150. X        return FAIL;
  151. X    }
  152. X    keypad(stdscr,TRUE);
  153. X
  154. X    /*
  155. X     * Save picture pointer for every field.
  156. X     */
  157. X    for(pic = 0; pic < _module.n_pictures; pic++) {
  158. X    for(fld = 0; fld < _module.picture[pic].n_fields; fld++) {
  159. X        _module.picture[pic].field[fld].picture = &_module.picture[pic];
  160. X    }
  161. X    }
  162. X
  163. X    raw();
  164. X    noecho();
  165. X
  166. X    return OK;
  167. X}
  168. X
  169. X/******************************************************************************
  170. X *
  171. X *        C F O R M S _ E N D
  172. X *        -------------------
  173. X *
  174. X * Description:
  175. X *    Turns off cforms.
  176. X *
  177. X *****************************************************************************/
  178. Xint
  179. Xcforms_end(void)
  180. X{
  181. X    cforms_inited = FALSE;
  182. X    move(23, 1);
  183. X    refresh();
  184. X    endwin();
  185. X    
  186. X    return OK;
  187. X}
  188. X
  189. X
  190. X/*******************************************************************************
  191. X *
  192. X *        P I C _ C A L L
  193. X *        ---------------
  194. X *
  195. X *
  196. X * Description:
  197. X *    This is the entry point for application into CForms
  198. X *
  199. X * Input:
  200. X *    pic        - Picture to call
  201. X *    field_name    - Name of field to start at, (NULL means first field).
  202. X *
  203. X * Global:
  204. X *    current.picture    - Is set up to point to this picture
  205. X *
  206. X ******************************************************************************/
  207. Xint
  208. Xpic_call(struct picture *pic, char *field_name)
  209. X{
  210. X    struct picture *old_picture = current.picture;
  211. X    struct field   *old_field = current.field;
  212. X    
  213. X    if (cforms_inited == FALSE) {
  214. X    fprintf(stderr, "** CForms not initialized **\n");
  215. X    return FAIL;
  216. X    }
  217. X
  218. X    if (pic == NULL) return FAIL;
  219. X    
  220. X    current.picture = pic;
  221. X    
  222. X    if (current.field) generate_event(EVENT_EXIT, 0);
  223. X
  224. X    draw_picture(pic);
  225. X    
  226. X    /*
  227. X     * To prevent generation of an event line exit for olf field but on new
  228. X     * picture, current field is set to NULL;
  229. X     */
  230. X     current.field = NULL;
  231. X     
  232. X     generate_event(EVENT_DRAW, 0);
  233. X     
  234. X     if (pic->n_fields != 0) {
  235. X    if (field_name) fld_move(field(field_name));
  236. X    else fld_move(fld_first());
  237. X    
  238. X    while(_leave_picture == FALSE) {
  239. X        hdl_field(current.field);
  240. X    }
  241. X    generate_event(EVENT_EXIT, 0);
  242. X    _leave_picture = FALSE;
  243. X    }
  244. X
  245. X    if (current.picture = old_picture) {
  246. X    draw_picture(current.picture);
  247. X    generate_event(EVENT_REFRESH, 0);
  248. X
  249. X    /*
  250. X     * Set to NULL for same reason as above.
  251. X     */
  252. X     current.field = NULL;
  253. X     fld_move(old_field);
  254. X    }
  255. X    return OK;
  256. X}
  257. X
  258. X
  259. X/*******************************************************************************
  260. X *
  261. X *        P I C T U R E
  262. X *        -------------
  263. X *
  264. X * Description:
  265. X *    Finds a picture with name as described by arguments in printf format.
  266. X *
  267. X ******************************************************************************/
  268. Xstruct picture *
  269. Xpicture(char *fmt, ...)
  270. X{
  271. X    static char pic_name[100];
  272. X    va_list arg;
  273. X    int i;
  274. X    
  275. X    va_start(arg, fmt);
  276. X    vsprintf(pic_name, fmt, arg);
  277. X    va_end(arg);
  278. X
  279. X    for(i = 0; i < _module.n_pictures; i++) {
  280. X    if (strequ(pic_name, _module.picture[i].name) == 0) {
  281. X        return &_module.picture[i];
  282. X    }
  283. X    }
  284. X    return NULL;
  285. X}
  286. X
  287. X
  288. X/*******************************************************************************
  289. X *
  290. X *        P I C _ L E A V E
  291. X *        -----------------
  292. X *
  293. X * Description:
  294. X *    Leave picture uppon exit of current event.
  295. X *
  296. X ******************************************************************************/
  297. Xint
  298. Xpic_leave()
  299. X{
  300. X    _leave_picture = TRUE;
  301. X    return OK;
  302. X}
  303. X
  304. X
  305. X/*******************************************************************************
  306. X *
  307. X *        P I C _ C L E A R
  308. X *        -----------------
  309. X *
  310. X * Description:
  311. X *    Clear all field of picture 'pic'.
  312. X *
  313. X ******************************************************************************/
  314. Xint
  315. Xpic_clear(struct picture *pic)
  316. X{
  317. X    int i, n;
  318. X    
  319. X    if (pic == NULL) pic = current.picture;
  320. X    if (pic == NULL) return FAIL;
  321. X    
  322. X    for(i = 0; i < pic->n_fields; i++) {
  323. X    pic->field[i].data[0] = 0;
  324. X    }
  325. X
  326. X    if (current.picture == pic) {
  327. X    for(i = 0; i < pic->n_fields; i++) {
  328. X        move(pic->field[i].pos.y + pic->y, pic->field[i].pos.x + pic->x);
  329. X        for(n = 0; n < pic->field[i].len; n++) {
  330. X            addch(' ');
  331. X        }
  332. X    }
  333. X    }
  334. X    return OK;
  335. X}
  336. X
  337. X
  338. X/*******************************************************************************
  339. X *
  340. X *        H D L _ F I E L D
  341. X *        -----------------
  342. X *
  343. X * Description:
  344. X *    Handles the intput of one field.
  345. X *
  346. X ******************************************************************************/
  347. Xstatic int
  348. Xhdl_field(struct field *fld)
  349. X{
  350. X    int (*check_p)();
  351. X    int x, y, ch, i, pos = 0;
  352. X    struct field *tmp_fld;
  353. X    
  354. X    move((y = fld->pos.y) + fld->picture->y, (x = fld->pos.x) + fld->picture->x);
  355. X    
  356. X    switch(fld->type & FLD_TYPE) {
  357. X    case FLD_STR:
  358. X        check_p = check_str;
  359. X        break;
  360. X        
  361. X    case FLD_ALNUM:
  362. X        check_p = check_alnum;
  363. X        break;
  364. X
  365. X    case FLD_INT:
  366. X        check_p = check_int;
  367. X        break;
  368. X        
  369. X    default:
  370. X        message("Illegal type, probably a bug");
  371. X    }
  372. X    
  373. X    i = strlen(fld->data);
  374. X    memset(fld->data + i, ' ', fld->len - i);
  375. X    fld->data[fld->len] = 0;
  376. X    
  377. X    while (refresh(), _leave_picture == FALSE && (ch = getch()) != EOF)
  378. X    {
  379. X    message_nr("");
  380. X    
  381. X    if (generate_event(EVENT_KEY, ch)) return OK;
  382. X    else if (ch == KEY_CTRL('w')) {
  383. X        clear();
  384. X        draw_picture(current.picture);
  385. X        if (generate_event(EVENT_REFRESH, 0)) return OK;
  386. X    }
  387. X    else if (ch == '\n') {
  388. X        if (fld->type & FLD_RIGHT) {
  389. X            adjust_right(fld->data, fld->len);
  390. X        }
  391. X    }
  392. X      else if (ch == KEY_LEFT) {
  393. X         if (pos <= 0) {
  394. X             if (generate_event(EVENT_PREVIOUS, 0)) return OK;
  395. X             if (tmp_fld = fld_left(current.field)) {
  396. X                 fld_move(tmp_fld);
  397. X                 return OK;
  398. X             }
  399. X             else message("Can't move left");
  400. X         }
  401. X         else {
  402. X             pos--;
  403. X        }
  404. X    }
  405. X    else if (ch == KEY_RIGHT) {
  406. X        if (pos >= fld->len - 1) {
  407. X            if (generate_event(EVENT_NEXT, 0)) return OK;
  408. X            if (tmp_fld = fld_right(current.field)) {
  409. X                fld_move(tmp_fld);
  410. X                return OK;
  411. X            }
  412. X            else message("Can't move right");
  413. X        }
  414. X        else {
  415. X            pos++;
  416. X        }
  417. X    }
  418. X    else if (fld->flags & FLD_PROTECTED) message("No input allowed");
  419. X    else if (ch == '\b') {
  420. X        if (pos > 0) {
  421. X        fld->data[--pos] = ' ';
  422. X        }
  423. X        fld->modified = 1;
  424. X    }
  425. X    else if (!isprint(ch)) message("Unknown key (%d)", ch);
  426. X    else if (check_p(&ch, fld->data, &pos, fld->len)) {
  427. X        if (fld->flags & FLD_UPPERCASE) ch = toupper(ch);
  428. X        fld->data[pos] = ch;
  429. X        if (pos < fld->len - 1) pos++;
  430. X        fld->modified = 1;
  431. X    }
  432. X    move(y + fld->picture->y, x + fld->picture->x);
  433. X    addstr(fld->data);
  434. X    move(y + fld->picture->y, x + fld->picture->x + pos);
  435. X    }
  436. X    return OK;
  437. X}
  438. X
  439. X
  440. X/*******************************************************************************
  441. X *
  442. X *        M E S S A G E, M E S S A G E _ N R
  443. X *        ----------------------------------
  444. X *
  445. X * Description:
  446. X *    Give message on bottom screen line. Work the same way as printf.
  447. X *    message_nr works the same as message but gives no refresh.
  448. X *
  449. X ******************************************************************************/
  450. Xint
  451. Xmessage(char *fmt, ...)
  452. X{
  453. X    va_list arg;
  454. X    va_start(arg, fmt);
  455. X    _message(fmt, arg);
  456. X    va_end(arg);
  457. X    refresh();
  458. X    return OK;
  459. X}
  460. X
  461. Xint
  462. Xmessage_nr(char *fmt, ...)
  463. X{
  464. X    va_list arg;
  465. X    va_start(arg, fmt);
  466. X    _message(fmt, arg);
  467. X    va_end(arg);
  468. X    return OK;
  469. X}
  470. X
  471. Xstatic int
  472. X_message(char *fmt, va_list arg)
  473. X{
  474. X    static char msg_str[160];
  475. X    char tmp_str[160];
  476. X    int x, y;
  477. X
  478. X    getyx(stdscr, y, x);
  479. X    
  480. X    move(23, 1);
  481. X    if (fmt != NULL) {
  482. X    vsprintf(tmp_str, fmt, arg);
  483. X    sprintf(msg_str, "%-50.50s", tmp_str);
  484. X    }
  485. X    addstr(msg_str);
  486. X    move(y, x);
  487. X    return OK;
  488. X}
  489. X
  490. X
  491. X/*******************************************************************************
  492. X *
  493. X *        C H E C K *
  494. X *        -----------
  495. X *
  496. X * Description:
  497. X *    Various check functions depending of type of field.
  498. X *    If function returnes TRUE, the char ch is put into field.
  499. X *
  500. X ******************************************************************************/
  501. Xstatic int
  502. Xcheck_int(int *ch, char *txt, int *pos, int len)
  503. X{
  504. X    int i;
  505. X    if (isdigit(*ch)) {
  506. X    return TRUE;
  507. X    }
  508. X
  509. X    if (isspace(*ch)) {
  510. X    for(i = 0; i < *pos; i++) {
  511. X        if (!isspace(txt[i])) {
  512. X        message("No space in middle of value");
  513. X        return FALSE;
  514. X        }
  515. X    }
  516. X    return TRUE;
  517. X    }
  518. X    message ("Must be digit");
  519. X    return FALSE;
  520. X}
  521. X
  522. Xstatic int
  523. Xcheck_alnum(int *ch, char *txt, int *pos, int len)
  524. X{
  525. X    if (isalnum(*ch) || isspace(*ch)) return TRUE;
  526. X    message("Must be alphanumeric");
  527. X    return FALSE;
  528. X}
  529. X
  530. Xstatic int
  531. Xcheck_str(int *ch, char *txt, int *pos, int len)
  532. X{
  533. X    if (isprint(*ch)) return TRUE;
  534. X    message("Must be printable");
  535. X    return FALSE;
  536. X}
  537. X
  538. X
  539. X/*******************************************************************************
  540. X *
  541. X *        A D J U S T _ R I G H T
  542. X *        -----------------------
  543. X *
  544. X * Description:
  545. X *    Adjust a text to the right
  546. X *
  547. X ******************************************************************************/
  548. Xstatic int
  549. Xadjust_right(char *txt, int len)
  550. X{
  551. X    int last_space = len - 1;
  552. X    
  553. X    while(isspace(txt[last_space]) && last_space >= 0)
  554. X    last_space--;
  555. X    last_space++;
  556. X    memcpy(txt + len - last_space, txt, last_space);
  557. X    memset(txt, ' ', len - last_space);
  558. X
  559. X    return OK;
  560. X}
  561. X
  562. X/*******************************************************************************
  563. X *
  564. X *        G E N E R A T E _ E V E N T
  565. X *        ---------------------------
  566. X *
  567. X * Description:
  568. X *    Generate a event of type and with code, and calls first function
  569. X *    for field or picture that should respond to the event.
  570. X *
  571. X * Input:
  572. X *    ev_type        - Event type, ex. EVENT_KEY, EVENT_ENTRY.
  573. X *    ev_code        - Code of event (not for all types), ex KEY_UP.
  574. X *
  575. X * Return:
  576. X *    Boolean, TRUE if event code was found and called. Events are not
  577. X *    called for 'event forget' statements (function = NULL).
  578. X *
  579. X ******************************************************************************/
  580. Xint
  581. Xgenerate_event(ev_type, ev_code)
  582. X{
  583. X    int i;
  584. X    
  585. X    for(i = 0; current.field && i < current.field->n_events; i++) {
  586. X        if (current.field->event[i].type == ev_type &&
  587. X            current.field->event[i].code == ev_code) {
  588. X                if (current.field->event[i].func == NULL) {
  589. X                    return FALSE;
  590. X                }
  591. X                (*current.field->event[i].func)();
  592. X                return TRUE;
  593. X        }
  594. X    }
  595. X
  596. X    for(i = 0; current.picture && i < current.picture->n_events; i++) {
  597. X        if (current.picture->event[i].type == ev_type &&
  598. X            current.picture->event[i].code == ev_code) {
  599. X                if (current.picture->event[i].func == NULL) {
  600. X                    return FALSE;
  601. X                }
  602. X                (*current.picture->event[i].func)();
  603. X                return TRUE;
  604. X        }
  605. X    }
  606. X
  607. X    for(i = 0;  i < _module.n_events; i++) {
  608. X        if (_module.event[i].type == ev_type &&
  609. X            _module.event[i].code == ev_code) {
  610. X                if (_module.event[i].func == NULL) {
  611. X                    return FALSE;
  612. X                }
  613. X                (*_module.event[i].func)();
  614. X                return TRUE;
  615. X        }
  616. X    }
  617. X
  618. X    return FALSE;
  619. X}
  620. X
  621. X
  622. X/*******************************************************************************
  623. X *
  624. X *        F L D _ M O V E
  625. X *        ---------------
  626. X *
  627. X * Description:
  628. X *    Move to field
  629. X *
  630. X * Input:
  631. X *    fld    - Field to move to.
  632. X *
  633. X * Return:
  634. X *    field move to.
  635. X *
  636. X ******************************************************************************/
  637. Xstruct field *
  638. Xfld_move(struct field *fld)
  639. X{
  640. X    if (fld == NULL) return current.field;
  641. X
  642. X    if (current.field) {
  643. X    generate_event(EVENT_EXIT, 0);
  644. X    }
  645. X    current.field = fld;
  646. X    generate_event(EVENT_ENTRY, 0);
  647. X
  648. X    return current.field;
  649. X}
  650. X
  651. X
  652. X/*******************************************************************************
  653. X *
  654. X *        F L D _ G E T
  655. X *        -------------
  656. X *
  657. X * Description:
  658. X *    Return text in field.
  659. X *
  660. X ******************************************************************************/
  661. Xchar *
  662. Xfld_get(struct field *fld)
  663. X{
  664. X    if (fld == NULL) fld = current.field;
  665. X    if (fld) return fld->data;
  666. X
  667. X    return "";
  668. X}
  669. X
  670. X
  671. X/*******************************************************************************
  672. X *
  673. X *        F L D _ S E T
  674. X *        -------------
  675. X *
  676. X * Description:
  677. X *    Set value for field.
  678. X *
  679. X ******************************************************************************/
  680. Xint
  681. Xfld_set(struct field *fld, char *data)
  682. X{
  683. X    int i;
  684. X    
  685. X    if (fld == NULL) fld = current.field;
  686. X    if (fld == NULL) return FAIL;
  687. X
  688. X    memset(fld->data, ' ', fld->len);
  689. X    i = strlen(data);
  690. X    if (i > fld->len) i = fld->len;
  691. X    strncpy(fld->data, data, i);
  692. X    fld->modified = 0;
  693. X    
  694. X    if (fld->picture == current.picture) {
  695. X     move(fld->pos.y + fld->picture->y, fld->pos.x + fld->picture->x);
  696. X    waddstr(stdscr, fld->data);
  697. X    }
  698. X    return OK;
  699. X}
  700. X
  701. X
  702. X/*******************************************************************************
  703. X *
  704. X *        F L D _ N S E T
  705. X *        ---------------
  706. X *
  707. X * Description:
  708. X *    Copy at most 'n' chars from input and set field to that.
  709. X *
  710. X ******************************************************************************/
  711. Xint
  712. Xfld_nset(struct field *fld, char *data, int n)
  713. X{
  714. X    char tmpstr[200];
  715. X    strncpy(tmpstr, data, n);
  716. X    tmpstr[n] = 0;
  717. X    return fld_set(fld, tmpstr);
  718. X}
  719. X
  720. X
  721. X/*******************************************************************************
  722. X *
  723. X *        F L D _ L E N
  724. X *        -------------
  725. X *
  726. X * Description:
  727. X *    Return length of field.
  728. X *
  729. X ******************************************************************************/
  730. Xint
  731. Xfld_len(struct field *fld)
  732. X{
  733. X    if (fld == NULL) fld = current.field;
  734. X    if (fld == NULL) return 0;
  735. X    return fld->len;
  736. X}
  737. X
  738. X/*******************************************************************************
  739. X *
  740. X *        F L D _ I S M O D I F I E D
  741. X *        ---------------------------
  742. X *
  743. X * Description:
  744. X *    Return TRUE if field has been modified since last fld_set.
  745. X *
  746. X ******************************************************************************/
  747. Xint
  748. Xfld_ismodified(struct field *fld)
  749. X{
  750. X    if (fld == NULL) fld = current.field;
  751. X    if (fld == NULL) return 0;
  752. X    return fld->modified;
  753. X}
  754. X
  755. X/*******************************************************************************
  756. X *
  757. X *        F L D _ T O U C H
  758. X *        -----------------
  759. X *
  760. X * Description:
  761. X *    Make field not modified.
  762. X *
  763. X ******************************************************************************/
  764. Xvoid
  765. Xfld_touch(struct field *fld)
  766. X{
  767. X    if (fld == NULL) fld = current.field;
  768. X    if (fld == NULL) return;
  769. X    fld->modified = 0;
  770. X}
  771. X
  772. X
  773. X/*******************************************************************************
  774. X *
  775. X *        F I E L D
  776. X *        ---------
  777. X *
  778. X * Description:
  779. X *    Return pointer to field with name. Name works as printf.
  780. X *
  781. X ******************************************************************************/
  782. Xstruct field *
  783. Xfield(char *fmt, ...)
  784. X{
  785. X    static char field_name[100];
  786. X    struct picture *pic;
  787. X    va_list arg;
  788. X    char *p;
  789. X    int i;
  790. X    
  791. X    va_start(arg, fmt);
  792. X    vsprintf(field_name, fmt, arg);
  793. X    va_end(arg);
  794. X    
  795. X    if (p = strchr(field_name, ':')) {
  796. X        *p++ = 0;
  797. X        pic = picture(field_name);
  798. X    }
  799. X    else {
  800. X        pic = current.picture;
  801. X        p = field_name;
  802. X    }
  803. X    
  804. X    if (pic == NULL) return NULL;
  805. X    
  806. X    for(i = 0; i < pic->n_fields; i++) {
  807. X        if(strequ(p, pic->field[i].name) == 0) return &pic->field[i];
  808. X    }
  809. X
  810. X    return NULL;
  811. X}
  812. X
  813. X/*******************************************************************************
  814. X *
  815. X *        S T R E Q U
  816. X *        -----------
  817. X *
  818. X * Description:
  819. X *    Case insensitive strcmp.
  820. X *
  821. X ******************************************************************************/
  822. Xint
  823. Xstrequ(char *s1, char *s2)
  824. X{
  825. X    while(*s1 && toupper(*s1) == toupper(*s2))
  826. X    s1++, s2++;
  827. X
  828. X    return toupper(*s1) - toupper(*s2);
  829. X}
  830. X
  831. X
  832. X/*******************************************************************************
  833. X *
  834. X *        F L D _ L E F T
  835. X *        ---------------
  836. X *
  837. X * Description:
  838. X *    Return pointer to a field left of 'fld'.
  839. X *
  840. X ******************************************************************************/
  841. Xstruct field *
  842. Xfld_left(struct field *fld)
  843. X{
  844. X    int i;
  845. X    int min_dist = 1000000;
  846. X    int dist;
  847. X    struct field *found = NULL;
  848. X    
  849. X    if (fld == NULL) fld = current.field;
  850. X    if (fld == NULL) fld = fld_first();
  851. X    if (fld == NULL) return NULL;
  852. X    
  853. X    for(i = 0; i < current.picture->n_fields; i++)
  854. X    {
  855. X        if (fld != ¤t.picture->field[i] &&
  856. X            current.picture->field[i].pos.x < fld->pos.x)
  857. X        {
  858. X        dist = (fld->pos.x - current.picture->field[i].pos.x) << 9;
  859. X        dist += abs(fld->pos.y - current.picture->field[i].pos.y);
  860. X        if (dist < min_dist)
  861. X        {
  862. X            min_dist = dist;
  863. X            found = ¤t.picture->field[i];
  864. X        }
  865. X    }
  866. X    }
  867. X
  868. X    return found;
  869. X}
  870. X
  871. X/*******************************************************************************
  872. X *
  873. X *        F L D _ R I G H T
  874. X *        -----------------
  875. X *
  876. X * Description:
  877. X *    Return pointer to a field right of 'fld'.
  878. X *
  879. X ******************************************************************************/
  880. Xstruct field *
  881. Xfld_right(struct field *fld)
  882. X{
  883. X    int i;
  884. X    int min_dist = 1000000;
  885. X    int dist;
  886. X    struct field *found = NULL;
  887. X    
  888. X    if (fld == NULL) fld = current.field;
  889. X    if (fld == NULL) fld = fld_first();
  890. X    if (fld == NULL) return NULL;
  891. X    
  892. X    for(i = 0; i < current.picture->n_fields; i++)
  893. X    {
  894. X        if (fld != ¤t.picture->field[i] &&
  895. X            current.picture->field[i].pos.x > fld->pos.x)
  896. X        {
  897. X        dist = (current.picture->field[i].pos.x - fld->pos.x) << 9;
  898. X        dist += abs(fld->pos.y - current.picture->field[i].pos.y);
  899. X        if (dist < min_dist)
  900. X        {
  901. X            min_dist = dist;
  902. X            found = ¤t.picture->field[i];
  903. X        }
  904. X    }
  905. X    }
  906. X
  907. X    return found;
  908. X}
  909. X
  910. X/*******************************************************************************
  911. X *
  912. X *        F L D _ D O W N
  913. X *        ---------------
  914. X *
  915. X * Description:
  916. X *    Return a pointer to field below 'fld'.
  917. X *
  918. X ******************************************************************************/
  919. Xstruct field *
  920. Xfld_down(struct field *fld)
  921. X{
  922. X    int i;
  923. X    int min_dist = 1000000;
  924. X    int dist;
  925. X    struct field *found = NULL;
  926. X    
  927. X    if (fld == NULL) fld = current.field;
  928. X    if (fld == NULL) fld = fld_first();
  929. X    if (fld == NULL) return NULL;
  930. X    
  931. X    for(i = 0; i < current.picture->n_fields; i++)
  932. X    {
  933. X        if (fld != ¤t.picture->field[i] &&
  934. X            current.picture->field[i].pos.y > fld->pos.y)
  935. X        {
  936. X        dist = (current.picture->field[i].pos.y - fld->pos.y) << 9;
  937. X        dist += abs(current.picture->field[i].pos.x - fld->pos.x);
  938. X        if (dist < min_dist)
  939. X        {
  940. X            min_dist = dist;
  941. X            found = ¤t.picture->field[i];
  942. X        }
  943. X    }
  944. X    }
  945. X
  946. X    return found;
  947. X}
  948. X
  949. X/*******************************************************************************
  950. X *
  951. X *        F L D _ U P 
  952. X *        -----------
  953. X *
  954. X * Description:
  955. X *    Return pointer to field above 'fld'.
  956. X *
  957. X ******************************************************************************/
  958. Xstruct field *fld_up(struct field *fld)
  959. X{
  960. X    int i;
  961. X    int min_dist = 1000000;
  962. X    int dist;
  963. X    struct field *found = NULL;
  964. X    
  965. X    if (fld == NULL) fld = current.field;
  966. X    if (fld == NULL) fld = fld_first();
  967. X    if (fld == NULL) return NULL;
  968. X    
  969. X    for(i = 0; i < current.picture->n_fields; i++)
  970. X    {
  971. X        if (fld != ¤t.picture->field[i] &&
  972. X            current.picture->field[i].pos.y < fld->pos.y)
  973. X        {
  974. X        dist = (fld->pos.y - current.picture->field[i].pos.y) << 9;
  975. X        dist += abs(current.picture->field[i].pos.x - fld->pos.x);
  976. X        if (dist < min_dist)
  977. X        {
  978. X            min_dist = dist;
  979. X            found = ¤t.picture->field[i];
  980. X        }
  981. X    }
  982. X    }
  983. X
  984. X    return found;
  985. X}
  986. X
  987. X/*******************************************************************************
  988. X *
  989. X *        F L D _ F I R S T
  990. X *        -----------------
  991. X *
  992. X * Description:
  993. X *    Find first field in picture.
  994. X *
  995. X ******************************************************************************/
  996. Xstruct field *
  997. Xfld_first(void)
  998. X{
  999. X    int i;
  1000. X    int min_dist = 1000000;
  1001. X    int dist;
  1002. X    struct field *found = NULL;
  1003. X    
  1004. X    for(i = 0; i < current.picture->n_fields; i++)
  1005. X    {
  1006. X    dist = current.picture->field[i].pos.y << 9;
  1007. X    dist += current.picture->field[i].pos.x;
  1008. X    if (dist < min_dist)
  1009. X    {
  1010. X        min_dist = dist;
  1011. X        found = ¤t.picture->field[i];
  1012. X    }
  1013. X    }
  1014. X
  1015. X    return found;
  1016. X}
  1017. X
  1018. X
  1019. X/*******************************************************************************
  1020. X *
  1021. X *        F L D _ L A S T
  1022. X *        ---------------
  1023. X *
  1024. X * Description:
  1025. X *    Find last field in picture.
  1026. X *
  1027. X ******************************************************************************/
  1028. Xstruct field *
  1029. Xfld_last(void)
  1030. X{
  1031. X    int i;
  1032. X    int max_dist = -1;
  1033. X    int dist;
  1034. X    struct field *found = NULL;
  1035. X
  1036. X    for(i = 0; i < current.picture->n_fields; i++)
  1037. X    {
  1038. X    dist = current.picture->field[i].pos.y << 9;
  1039. X    dist += current.picture->field[i].pos.x;
  1040. X    if (dist > max_dist)
  1041. X    {
  1042. X        max_dist = dist;
  1043. X        found = ¤t.picture->field[i];
  1044. X    }
  1045. X    }
  1046. X
  1047. X    return found;
  1048. X}
  1049. X
  1050. X/*******************************************************************************
  1051. X *
  1052. X *        F L D _ N E X T
  1053. X *        ---------------
  1054. X *
  1055. X * Description:
  1056. X *    Find next field in picture.
  1057. X *
  1058. X ******************************************************************************/
  1059. Xstruct field *
  1060. Xfld_next(struct field *fld)
  1061. X{
  1062. X    int i;
  1063. X    int min_dist = 1000000;
  1064. X    int dist;
  1065. X    struct field *found = NULL;
  1066. X
  1067. X    if (fld == NULL) fld = current.field;
  1068. X    if (fld == NULL) fld = fld_first();
  1069. X    if (fld == NULL) return NULL;
  1070. X    
  1071. X    for(i = 0; i < current.picture->n_fields; i++)
  1072. X    {
  1073. X    dist = (current.picture->field[i].pos.y - fld->pos.y)<< 9;
  1074. X    dist += current.picture->field[i].pos.x - fld->pos.x;
  1075. X    
  1076. X    if (dist > 0 && dist < min_dist)
  1077. X    {
  1078. X        min_dist = dist;
  1079. X        found = ¤t.picture->field[i];
  1080. X    }
  1081. X    }
  1082. X
  1083. X    return found;
  1084. X}
  1085. X
  1086. X/*******************************************************************************
  1087. X *
  1088. X *        F L D _ P R E V I O U S
  1089. X *        -----------------------
  1090. X *
  1091. X * Description:
  1092. X *    Find previoud field in picture.
  1093. X *
  1094. X ******************************************************************************/
  1095. Xstruct field *fld_previous(struct field *fld)
  1096. X{
  1097. X    int i;
  1098. X    int min_dist = 1000000;
  1099. X    int dist;
  1100. X    struct field *found = NULL;
  1101. X    
  1102. X    for(i = 0; i < current.picture->n_fields; i++)
  1103. X    {
  1104. X    dist = (fld->pos.y - current.picture->field[i].pos.y) << 9;
  1105. X    dist += fld->pos.x - current.picture->field[i].pos.x;
  1106. X    
  1107. X    if (dist > 0 && dist < min_dist)
  1108. X    {
  1109. X        min_dist = dist;
  1110. X        found = ¤t.picture->field[i];
  1111. X    }
  1112. X    }
  1113. X
  1114. X    return found;
  1115. X}
  1116. X
  1117. X/*******************************************************************************
  1118. X *
  1119. X *        F L D _ I S E M P T Y
  1120. X *        ---------------------
  1121. X *
  1122. X * Description:
  1123. X *    Return true if field contains only space or nulls.
  1124. X *
  1125. X ******************************************************************************/
  1126. Xint
  1127. Xfld_isempty(struct field *fld)
  1128. X{
  1129. X    int i;
  1130. X    
  1131. X    if (fld == NULL) return TRUE;
  1132. X    
  1133. X    for(i = 0; i < fld->len; i++)
  1134. X    {
  1135. X        if (fld->data[i] == 0) return TRUE;
  1136. X        if (!isspace(fld->data[i])) return FALSE;
  1137. X    }
  1138. X    return TRUE;
  1139. X}
  1140. X
  1141. X/*******************************************************************************
  1142. X *
  1143. X *        D R A W _ P I C T U R E
  1144. X *        -----------------------
  1145. X *
  1146. X * Description:
  1147. X *    Draw all literals and field in a picture.
  1148. X *
  1149. X ******************************************************************************/
  1150. Xstatic int
  1151. Xdraw_picture(struct picture *pic)
  1152. X{
  1153. X    int n;
  1154. X    int r;
  1155. X    char space[100];
  1156. X
  1157. X
  1158. X    if (pic == NULL) return FAIL;
  1159. X    
  1160. X    memset(space, ' ', pic->width);
  1161. X    space[pic->width] = 0;
  1162. X     
  1163. X    for(r = pic->y; r < pic->y + pic->height; r++) {
  1164. X    move(r, pic->x);
  1165. X    addstr(space);
  1166. X    }    
  1167. X
  1168. X    for(n = 0; n < pic->n_literals; n++) {
  1169. X    move(pic->literal[n].pos.y + pic->y, pic->literal[n].pos.x + pic->x);
  1170. X    addstr(pic->literal[n].value);
  1171. X    }
  1172. X    
  1173. X    for(n = 0; n < pic->n_fields; n++) {
  1174. X        if (pic->field[n].lvalue) {
  1175. X            move(pic->field[n].pos.y + pic->y,
  1176. X                 pic->field[n].pos.x - strlen(pic->field[n].lvalue) + pic->x);
  1177. X            addstr(pic->field[n].lvalue);
  1178. X        }
  1179. X
  1180. X        if (pic->field[n].rvalue) {
  1181. X            move(pic->field[n].pos.y + pic->y,
  1182. X                 pic->field[n].pos.x + pic->field[n].len + pic->x);
  1183. X            addstr(pic->field[n].rvalue);
  1184. X        }
  1185. X        move(pic->field[n].pos.y + pic->y, pic->field[n].pos.x + pic->x);
  1186. X        addstr(pic->field[n].data);
  1187. X    }
  1188. X
  1189. X    message_nr(NULL);
  1190. X
  1191. X    return OK;
  1192. X}
  1193. X
  1194. X/******************************************************************************
  1195. X *
  1196. X *                        S I G C A T C H
  1197. X *                        ---------------
  1198. X * Description:
  1199. X *        Catches a signal, cleans up and exits.
  1200. X *
  1201. X *****************************************************************************/
  1202. Xstatic int
  1203. Xsigcatch(void)
  1204. X{
  1205. X    cforms_end();
  1206. X    exit(1);
  1207. X}
  1208. END_OF_FILE
  1209. if test 27545 -ne `wc -c <'src/cflib.c'`; then
  1210.     echo shar: \"'src/cflib.c'\" unpacked with wrong size!
  1211. fi
  1212. # end of 'src/cflib.c'
  1213. fi
  1214. echo shar: End of archive 3 \(of 3\).
  1215. cp /dev/null ark3isdone
  1216. MISSING=""
  1217. for I in 1 2 3 ; do
  1218.     if test ! -f ark${I}isdone ; then
  1219.     MISSING="${MISSING} ${I}"
  1220.     fi
  1221. done
  1222. if test "${MISSING}" = "" ; then
  1223.     echo You have unpacked all 3 archives.
  1224.     rm -f ark[1-9]isdone
  1225. else
  1226.     echo You still need to unpack the following archives:
  1227.     echo "        " ${MISSING}
  1228. fi
  1229. ##  End of shell archive.
  1230. exit 0
  1231.