home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / mush / part07 < prev    next >
Internet Message Format  |  1991-04-21  |  51KB

  1. From: argv@zipcode.com (Dan Heller)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i064:  mush - Mail User's Shell, Part07/22
  4. Message-ID: <1991Apr21.025013.11375@sparky.IMD.Sterling.COM>
  5. Date: 21 Apr 91 02:50:13 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 5f3df319 237aaa55 fa7b288c 6ca14a4c
  8.  
  9. Submitted-by: Dan Heller <argv@zipcode.com>
  10. Posting-number: Volume 18, Issue 64
  11. Archive-name: mush/part07
  12. Supersedes: mush: Volume 12, Issue 28-47
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file dates.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 7; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping dates.c'
  32. else
  33. echo 'x - continuing file dates.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'dates.c' &&
  35. X
  36. X    (void) strncpy(zone, tz, 7), zone[7] = 0;
  37. X    return T;
  38. }
  39. X
  40. /* Time() returns a string according to criteria:
  41. X *   if "now" is 0, then the current time is gotten and used.
  42. X *       else, use the time described by now
  43. X *   opts points to a string of args which is parsed until an unknown
  44. X *       arg is found and opts will point to that upon return.
  45. X *   valid args are T (time of day), D (day of week), M (month), Y (year),
  46. X *       N (number of day in month -- couldn't think of a better letter).
  47. X */
  48. char *
  49. Time(opts, now)
  50. register char *opts;
  51. long now;
  52. {
  53. X    static char time_buf[30];
  54. X    struct tm       *T;
  55. X    register char *p = time_buf;
  56. X    long      x;
  57. X
  58. X    if (!opts)
  59. X    return NULL;
  60. X    if (now)
  61. X    x = now;
  62. X    else
  63. X    (void) time(&x);
  64. X    T = localtime(&x);
  65. X    for (;; opts++) {
  66. X    switch(*opts) {
  67. X        case 'T':
  68. X        if (ison(glob_flags, MIL_TIME))
  69. X            (void) sprintf(p, "%2d:%02d", T->tm_hour, T->tm_min);
  70. X        else
  71. X            (void) sprintf(p, "%d:%02d", (T->tm_hour) ?
  72. X              ((T->tm_hour <= 12) ? T->tm_hour : T->tm_hour - 12) :
  73. X              12, T->tm_min);
  74. X        when 'D': case 'W': (void) strcpy(p, day_names[T->tm_wday]);
  75. X        when 'M': (void) strcpy(p, month_names[T->tm_mon]);
  76. X        when 'y': (void) sprintf(p, "%d", T->tm_year);
  77. X        when 'Y': (void) sprintf(p, "%d", T->tm_year + 1900);
  78. X        when 'N': (void) sprintf(p, "%d", T->tm_mday);
  79. X        otherwise: *--p = 0; return time_buf;
  80. X    }
  81. X    p += strlen(p);
  82. X    *p++ = ' ';
  83. X    }
  84. }
  85. X
  86. /* parse date and return a string that looks like
  87. X *   %ld%3c%s    gmt_in_secs weekday orig_timezone
  88. X * This function is a bunch of scanfs on known date formats.  Don't
  89. X * trust the "weekday" name fields because they may not be spelled
  90. X * right, or have the correct punctuation.  Figure it out once the
  91. X * year and month and date have been determined.
  92. X */
  93. char *
  94. parse_date(p)
  95. register char *p;
  96. {
  97. X    /* When scanf-ing if month isn't a month, it could be a _long_ string.
  98. X     * this is also the static buffer whose address we return.
  99. X     */
  100. X    static char month[64];
  101. X    char Wkday[4], Zone[12], dst[4];
  102. X    char a_or_p;
  103. X    int Month = 0, Day = 0, Year = 0;
  104. X    int Hours = -1, Mins = -1;
  105. X    struct tm T;
  106. X
  107. X    Zone[0] = dst[0] = 0;
  108. X    skipspaces(0);
  109. X
  110. X    /* programmer's note -- there are too many scanfs here for some compilers
  111. X     * to put them all into one if statement.  Use goto's :-(  Also reset
  112. X     * Zone[0] after any sscanf() that could corrupt it on a partial match.
  113. X     *
  114. X     * Not yet handling all possible combinations of mailers using two-word
  115. X     * time zones, e.g. MET DST instead of MEST.  Only the specific case
  116. X     * where this was reported has been handled here.
  117. X     */
  118. X
  119. X    /* RFC822 formats and minor variations -- order important */
  120. X
  121. X    /*   day_number month_name year_number time timezone */
  122. X    if (sscanf(p, "%d %s %d %d:%d:%*d %7s %3s",
  123. X        &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day)
  124. X    goto gotit;
  125. X    Zone[0] = dst[0] = 0;
  126. X    if (sscanf(p, "%d %s %d %d:%d %7s",
  127. X        &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day)
  128. X    goto gotit;
  129. X    Zone[0] = dst[0] = 0;
  130. X    /*   day_name day_number month_name year_number time timezone */
  131. X    if (sscanf(p, "%*s %d %s %d %d:%d:%*d %7s %3s",
  132. X        &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day)
  133. X    goto gotit;
  134. X    Zone[0] = dst[0] = 0;
  135. X    if (sscanf(p, "%*s %d %s %d %d:%d %7s %3s",
  136. X        &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day)
  137. X    goto gotit;
  138. X    Zone[0] = dst[0] = 0;
  139. X
  140. X    /* Ctime format (From_ lines) -- timezone almost never found */
  141. X
  142. X    /*   day_name month_name day_number time year_number */
  143. X    if (sscanf(p, "%*s %s %d %d:%d:%*d %d",
  144. X        month, &Day, &Hours, &Mins, &Year) == 5)
  145. X    goto gotit;
  146. X    /*   day_name month_name day_number time timezone year_number */
  147. X    if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %d",
  148. X        month, &Day, &Hours, &Mins, Zone, &Year) == 6)
  149. X    goto gotit;
  150. X    Zone[0] = 0;
  151. X    if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %3s %d",
  152. X        month, &Day, &Hours, &Mins, Zone, dst, &Year) == 7)
  153. X    goto gotit;
  154. X    Zone[0] = dst[0] = 0;
  155. X
  156. X    /* Other common variants */
  157. X
  158. X    /*   day_number month_name year_number time-timezone (day) */
  159. X    /*                                       ^no colon separator */
  160. X    if (sscanf(p, "%d %s %d %2d%2d-%6[0123456789]",
  161. X        &Day, month, &Year, &Hours, &Mins, &Zone[1]) == 6) {
  162. X    Zone[0] = '-';
  163. X    goto gotit;
  164. X    }
  165. X    if (sscanf(p, "%d %s %d %2d%2d-%7s",
  166. X        &Day, month, &Year, &Hours, &Mins, Zone) == 6)
  167. X    goto gotit;
  168. X    Zone[0] = 0;
  169. X
  170. X    /*   day_number month_name year_number time timezone    */
  171. X    /*                                      ^no colon separator */
  172. X    /*   (This is the odd one in the RFC822 examples section;    */
  173. X    /*    also catches the slop from partial hits above.)    */
  174. X    if (sscanf(p, "%d %s %d %2d%2d %7s",
  175. X        &Day, month, &Year, &Hours, &Mins, Zone) >= 5 && Day)
  176. X    goto gotit;
  177. X    Zone[0] = 0;
  178. X    
  179. X    Zone[1] = 0;    /* Yes, Zone[1] -- tested below */
  180. X
  181. X    /*   day_number month_name year_number, time "-" ?? */
  182. X    if (sscanf(p,"%d %s %d, %d:%d:%*d -%6[0123456789]",
  183. X        &Day, month, &Year, &Hours, &Mins, &Zone[1]) >= 5 && Day) {
  184. X    if (Zone[1])
  185. X        Zone[0] = '-';
  186. X    goto gotit;
  187. X    }
  188. X
  189. X    /*   day_number month_name year_number 12_hour_time a_or_p */
  190. X    if (sscanf(p, "%d %s %d %d:%d:%*d %cm %7s",
  191. X        &Day, month, &Year, &Hours, &Mins, &a_or_p, Zone) >= 6) {
  192. X    if (a_or_p == 'p')
  193. X        Hours += 12;
  194. X    goto gotit;
  195. X    }
  196. X
  197. X    /*   day_name month_name day_number year_number time */
  198. X    if (sscanf(p, "%*s %s %d %d %d:%d:%*d %7s",
  199. X        month, &Day, &Year, &Hours, &Mins, Zone) >= 5)
  200. X    goto gotit;
  201. X    Zone[0] = 0;
  202. X    if (sscanf(p, "%*s %s %d %d %d:%d %7s",
  203. X        month, &Day, &Year, &Hours, &Mins, Zone) >= 5)
  204. X    goto gotit;
  205. X    Zone[0] = 0;
  206. X
  207. X    /*   day_name month_name day_number time timezone year_number */
  208. X    if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %d",
  209. X        month, &Day, &Hours, &Mins, Zone, &Year) == 6)
  210. X    goto gotit;
  211. X    Zone[0] = 0;
  212. X    if (sscanf(p, "%*s %s %d %d:%d %7s %d",
  213. X        month, &Day, &Hours, &Mins, Zone, &Year) == 6)
  214. X    goto gotit;
  215. X    Zone[0] = 0;
  216. X
  217. X    /*   day_number-month_name-year time */
  218. X    if (sscanf(p,"%d-%[^-]-%d %d:%d", &Day, month, &Year, &Hours, &Mins) == 5)
  219. X    goto gotit;
  220. X
  221. X    /*   day_name, day_number-month_name-year time */
  222. X    if (sscanf(p,"%*s %d-%[^-]-%d %d:%d",
  223. X        &Day, month, &Year, &Hours, &Mins) == 5)
  224. X    goto gotit;
  225. X
  226. X    /*   year_number-month_number-day_number time */
  227. X    if (sscanf(p, "%d-%d-%d %d:%d", &Year, &Month, &Day, &Hours, &Mins) == 5)
  228. X    goto gotit;
  229. X
  230. X    /*   month_name day_number time year Zone */
  231. X    /*   (ctime, but without the day name)    */
  232. X    if (sscanf(p, "%s %d %d:%d:%*d %d %7s",
  233. X        month, &Day, &Hours, &Mins, &Year, Zone) >= 5)
  234. X    goto gotit;
  235. X    Zone[0] = 0;
  236. X
  237. X    if (ison(glob_flags, WARNING))
  238. X    print("Unknown date format: %s\n", p);
  239. X    return NULL;
  240. X
  241. gotit:
  242. X    if (!lcase_strncmp(dst, "dst", -1)) {
  243. X    (void) strcat(Zone, " ");
  244. X    (void) strcat(Zone, dst);
  245. X    }
  246. X    if (Year > 1900)
  247. X    Year -= 1900;
  248. X    if (!Month && (Month = month_to_n(month)) == -1) {
  249. X    print("bad month: %s\n", p);
  250. X    return NULL;
  251. X    }
  252. X    if (Zone[0] == 0) {
  253. X    /* Use local time zone if none found -- important for date_recv */
  254. X    (void) time_n_zone(Zone);
  255. X    }
  256. X    {
  257. X    /* Lots of foolishness with casts for Xenix-286 16-bit ints */
  258. X
  259. X    long days_ctr;    /* 16-bit ints overflowed Sept 12, 1989 */
  260. X
  261. X        days_ctr = ((long)Year * 365L) + ((Year + 3) / 4);
  262. X        days_ctr += mtbl[Month-1] + Day + 6;
  263. X        if (Month > 2 && (Year % 4 == 0))
  264. X        days_ctr++;
  265. X        (void) (sprintf(Wkday, "%.3s", day_names[(int)(days_ctr % 7L)]));
  266. X    }
  267. X    T.tm_sec = 0;        /* not recorded, so ignore it */
  268. X    T.tm_min = Mins;
  269. X    T.tm_hour = Hours;
  270. X    T.tm_mday = Day;
  271. X    T.tm_mon = Month - 1;
  272. X    T.tm_year = Year;
  273. X    T.tm_wday = T.tm_yday = 0;    /* not used in time2gmt() */
  274. X    T.tm_isdst = 0;        /* determined from Zone */
  275. X    return sprintf(month, "%ld%s%s", time2gmt(&T, Zone, 1), Wkday, Zone);
  276. }
  277. X
  278. /* pass a string in the standard date format, put into string.
  279. X * return values in buffers provided they are not null.
  280. X */
  281. char *
  282. date_to_string(Date, Yr, Mon, Day, Wkday, Tm, Zone, ret_buf)
  283. char *Date, *Yr, *Mon, *Day, *Wkday, *Tm, *Zone, *ret_buf;
  284. {
  285. X    long gmt;
  286. X    struct tm *T;
  287. X    char a_or_p, *p = ret_buf;
  288. X
  289. X    Zone[0] = 0;
  290. X    (void) sscanf(Date, "%ld%3c%s", &gmt, Wkday, Zone);
  291. X    Wkday[3] = 0;
  292. X    gmt += getzoff(Zone);
  293. X    T = gmtime(&gmt);
  294. X    a_or_p = (T->tm_hour < 12)? 'a': 'p';
  295. X
  296. X    (void) sprintf(Yr, "%d", T->tm_year + 1900);
  297. X    (void) sprintf(Day, "%d", T->tm_mday);
  298. X    (void) strcpy(Mon, month_names[T->tm_mon]);
  299. X    p += strlen(sprintf(p, "%s %2.d, ", Mon, T->tm_mday));
  300. X
  301. X    if (ison(glob_flags, MIL_TIME))
  302. X    (void) sprintf(p, "%2d:%02d",T->tm_hour,T->tm_min);
  303. X    else
  304. X    (void) sprintf(p, "%2.d:%02d%cm",
  305. X          (T->tm_hour)? (T->tm_hour <= 12)? T->tm_hour: T->tm_hour-12: 12,
  306. X          T->tm_min, a_or_p);
  307. X    (void) strcpy(Tm, p);
  308. X
  309. X    return ret_buf;
  310. }
  311. X
  312. /* pass a string in the internal mush date format.
  313. X * return pointer to static buffer holding ctime-format date.
  314. X */
  315. char *
  316. date_to_ctime(Date)
  317. char *Date;
  318. {
  319. X    static char ret_buf[32];
  320. X    long gmt;
  321. X
  322. X    ret_buf[0] = 0;
  323. X    (void) sscanf(Date, "%ld", &gmt);
  324. X    (void) strcpy(ret_buf, ctime(&gmt));
  325. X
  326. X    return ret_buf;
  327. }
  328. X
  329. /*
  330. X * Build a date string according to the specification in the RFC for Date:
  331. X */
  332. char *
  333. rfc_date(buf)
  334. char buf[];
  335. {
  336. X    struct tm *T;
  337. X    char zone[8];
  338. X
  339. X    T = time_n_zone(zone);
  340. #ifndef USA
  341. X    {
  342. X    long zoff_hr, zoff_sec = getzoff(zone);
  343. X    if (zoff_sec < 0) {
  344. X        zone[0] = '-';
  345. X        zoff_sec = -zoff_sec; 
  346. X    } else
  347. X        zone[0] = '+';
  348. X    zoff_hr = zoff_sec / 3600;
  349. X    zoff_sec -= zoff_hr * 3600;
  350. X    (void) sprintf(&zone[1], "%02d%02d", zoff_hr, zoff_sec / 60);
  351. X    }
  352. #endif /* !USA */
  353. X
  354. X    return sprintf(buf, "%s, %d %s %d %02d:%02d:%02d %s",
  355. X    day_names[T->tm_wday],    /* day name */
  356. X    T->tm_mday,        /* day of the month */
  357. X    month_names[T->tm_mon],    /* month name */
  358. X    T->tm_year + 1900,    /* year number */
  359. X    T->tm_hour,        /* hours (24hr) */
  360. X    T->tm_min, T->tm_sec,    /* mins/secs */
  361. X    zone);            /* timezone */
  362. }
  363. X
  364. #define JAN    1
  365. #define FEB    2
  366. #define MAR    3
  367. #define APR    4
  368. #define MAY    5
  369. #define JUN    6
  370. #define JUL    7
  371. #define AUG    8
  372. #define SEP    9
  373. #define OCT    10
  374. #define NOV    11
  375. #define DEC    12
  376. X
  377. /* stolen direct from ELM */
  378. month_to_n(name)
  379. register char *name;
  380. {
  381. X    /** return the month number given the month name... **/
  382. X
  383. X    register char ch;
  384. X
  385. X    switch (lower(*name)) {
  386. X    case 'a' : if ((ch = lower(name[1])) == 'p')
  387. X               return(APR);
  388. X           else if (ch == 'u')
  389. X               return(AUG);
  390. X           else return(-1);    /* error! */
  391. X    case 'd' : return(DEC);
  392. X    case 'f' : return(FEB);
  393. X    case 'j' : if ((ch = lower(name[1])) == 'a')
  394. X               return(JAN);
  395. X           else if (ch == 'u') {
  396. X             if ((ch = lower(name[2])) == 'n')
  397. X             return(JUN);
  398. X             else if (ch == 'l')
  399. X             return(JUL);
  400. X             else return(-1);        /* error! */
  401. X           }
  402. X           else return(-1);        /* error */
  403. X    case 'm' : if ((ch = lower(name[2])) == 'r')
  404. X               return(MAR);
  405. X           else if (ch == 'y')
  406. X               return(MAY);
  407. X           else return(-1);        /* error! */
  408. X    case 'n' : return(NOV);
  409. X    case 'o' : return(OCT);
  410. X    case 's' : return(SEP);
  411. X    default  : return(-1);
  412. X    }
  413. }
  414. SHAR_EOF
  415. echo 'File dates.c is complete' &&
  416. chmod 0644 dates.c ||
  417. echo 'restore of dates.c failed'
  418. Wc_c="`wc -c < 'dates.c'`"
  419. test 15621 -eq "$Wc_c" ||
  420.     echo 'dates.c: original size 15621, current size' "$Wc_c"
  421. rm -f _shar_wnt_.tmp
  422. fi
  423. # ============= digestify ==============
  424. if test -f 'digestify' -a X"$1" != X"-c"; then
  425.     echo 'x - skipping digestify (File already exists)'
  426.     rm -f _shar_wnt_.tmp
  427. else
  428. > _shar_wnt_.tmp
  429. echo 'x - extracting digestify (Text)'
  430. sed 's/^X//' << 'SHAR_EOF' > 'digestify' &&
  431. #! ../bin/mush -F!
  432. #
  433. # Mush digestifier.  Makes a folder or a list of messages into a digest.
  434. #
  435. # A "digest" is a collection of E-mail messages bundled together into a
  436. # single message for ease of redistribution.  The individual messages
  437. # in the digest are called "articles".  Each article has a small set of
  438. # essential headers (usually From:, Date:, and Subject:) and is divided
  439. # from the preceding and following articles by an "article separator"
  440. # string (usually eight hyphens, "--------").  The Mush built-in command
  441. # "undigest" unpacks most digests, including those made by this script.
  442. #
  443. # Usage:
  444. #  From your shell:        digestify -f mailbox
  445. #  From within mush:    
  446. #    First:        cmd digest "set digest = '\!*' ; source digestify"
  447. #    Then:        digest [msg-list]
  448. #    Or:        message-selection-command | digest
  449. #
  450. # Note that by default it makes a digest of the ENTIRE folder!
  451. #
  452. X
  453. #
  454. # Rudimentary sanity checks
  455. #
  456. if ! $?version
  457. X    echo "You must have Mush version 7.0 or higher to run this script"
  458. X    exit
  459. endif
  460. if ! $?thisfolder
  461. X    echo "You can't use this script as an init file; try using -F"
  462. X    exit
  463. endif
  464. X
  465. #
  466. # Set up defaults
  467. #
  468. if ! $?digest
  469. X    set digest = *
  470. X    if $?interact
  471. X    unset interact        # Assume non-interactive if no input list
  472. X    endif
  473. else
  474. X    set interact        # Note that this is interactive
  475. X    if "X$digest" == X
  476. X        set digest = *        # Default to all messages for empty input
  477. X    else
  478. X    $digest | set digest    # Pre-expand message numbers
  479. X    endif
  480. endif
  481. X
  482. #
  483. # Suppress any "that isn't set" messages from "unset"
  484. #
  485. if $?warning
  486. X    set savewarn
  487. endif
  488. unset warning oldpre oldpost oldindent oldign oldshow
  489. X
  490. #
  491. # Save everything in case the user wants it back.
  492. # Could wrap all this with "if $?interact" but this script
  493. # might be read by "mush -F", in which case we need this.
  494. #
  495. if $?pre_indent_str
  496. X    set oldpre = "$pre_indent_str"
  497. endif
  498. if $?post_indent_str
  499. X    set oldpost = "$post_indent_str"
  500. endif
  501. if $?indent_str
  502. X    set oldindent = "$indent_str"
  503. endif
  504. if $?alwaysignore
  505. X    set oldign = "$alwaysignore"
  506. endif
  507. if $?show_hdrs
  508. X    set oldshow = "$show_hdrs"
  509. endif
  510. if $?quiet
  511. X    set oldquiet = "$quiet"
  512. endif
  513. if $?no_expand
  514. X    set savenoex
  515. endif
  516. X
  517. #
  518. # Prepare to form the digest.
  519. #
  520. set indent_str no_expand alwaysignore=include quiet=await,newmail
  521. unset post_indent_str
  522. alias DIGEST $thisfolder        # Any target in place of $thisfolder
  523. set pre_indent_str="--------"        # Insert your digest separator here
  524. set show_hdrs=from,date,subject        # Add any other headers you want
  525. X
  526. #
  527. # Now do it.  All that work for a two-line operation ....
  528. # NOTE: If you change DIGEST above, remove the "await" command here!
  529. # Backslashes prevent any cmd expansion from confusing us.
  530. #
  531. \delete $digest
  532. \mail -UH /dev/null -I $digest -s "Digest of $thisfolder" DIGEST; \await -T 1
  533. X
  534. #
  535. # Clean out the deleted stuff if not interactive
  536. #
  537. if ! $?interact
  538. X    \update
  539. endif
  540. X
  541. #
  542. # Be neat and put everything back the way it was.
  543. #
  544. unset indent_str no_expand alwaysignore quiet pre_indent_str show_hdrs
  545. unalias DIGEST
  546. if $?savenoex
  547. X    set no_expand
  548. endif
  549. if $?oldquiet
  550. X    set quiet = "$oldquiet"
  551. endif
  552. if $?oldpre
  553. X    set pre_indent_str = "$oldpre"
  554. endif
  555. if $?oldpost
  556. X    set post_indent_str = "$oldpost"
  557. endif
  558. if $?oldindent
  559. X    set indent_str = "$oldindent"
  560. endif
  561. if $?oldign
  562. X    set alwaysignore = "$oldign"
  563. endif
  564. if $?oldshow
  565. X    set show_hdrs = "$oldshow"
  566. endif
  567. unset oldpre oldpost oldindent oldign oldshow oldquiet nonoex digest
  568. if $?savewarn
  569. X    unset savewarn
  570. X    set warning
  571. endif
  572. SHAR_EOF
  573. chmod 0755 digestify ||
  574. echo 'restore of digestify failed'
  575. Wc_c="`wc -c < 'digestify'`"
  576. test 3468 -eq "$Wc_c" ||
  577.     echo 'digestify: original size 3468, current size' "$Wc_c"
  578. rm -f _shar_wnt_.tmp
  579. fi
  580. # ============= doproc.c ==============
  581. if test -f 'doproc.c' -a X"$1" != X"-c"; then
  582.     echo 'x - skipping doproc.c (File already exists)'
  583.     rm -f _shar_wnt_.tmp
  584. else
  585. > _shar_wnt_.tmp
  586. echo 'x - extracting doproc.c (Text)'
  587. sed 's/^X//' << 'SHAR_EOF' > 'doproc.c' &&
  588. /* @(#)doproc.c        (c) copyright    10/18/86 (Dan Heller) */
  589. X
  590. /* do main panel item procedures */
  591. #include "mush.h"
  592. X
  593. extern void start_textsw_edit();
  594. extern Panel get_compose_panel();
  595. void set_comp_items();
  596. X
  597. extern Panel_item
  598. X    file_item, folder_text_item, folder_item, msg_num_item, read_item,
  599. X    reply_item, save_item, sub_hdr_item[6];
  600. X
  601. /* following macro is for the next two procedures */
  602. #define hdr_item(item) \
  603. X    (item == sub_hdr_item[0] || item == sub_hdr_item[1] || \
  604. X     item == sub_hdr_item[2] || item == sub_hdr_item[3] || \
  605. X     item == sub_hdr_item[4] || item == sub_hdr_item[5])
  606. X
  607. void
  608. delete_mail(item, value, event)
  609. register Panel_item item;
  610. int value;
  611. register Event *event;
  612. {
  613. X    int val = value; /* save cuz we reset value immediately */
  614. X    u_long bang = ison(glob_flags, IGN_BANG);
  615. X    char buf[128];
  616. X
  617. X    (void) panel_set(item, PANEL_VALUE, 0, 0);
  618. X    if (hdr_item(item) && event_id(event) != MS_LEFT || val == 2) {
  619. X    help(0, "delete", tool_help);
  620. X    return;
  621. X    }
  622. X    /* delete current message */
  623. X    wprint(sprintf(buf, "\\%sdelete %s\n",
  624. X    ((event_id(event) == MS_LEFT || val == 0)? "" : "un"),
  625. X    panel_get_value(msg_num_item)) + 1); /* +1 skips the backslash */
  626. X    turnon(glob_flags, IGN_BANG);
  627. X    (void) cmd_line(buf, msg_list);
  628. X    if (!bang)
  629. X    turnoff(glob_flags, IGN_BANG);
  630. }
  631. X
  632. void
  633. read_mail(item, value, event)
  634. Panel_item item;
  635. Event *event;
  636. {
  637. X    int this_msg = current_msg;
  638. X
  639. X    /* check "event" in case we were called from hdr_sw.c
  640. X     * in which case event would be NULL
  641. X     */
  642. X    if (event && event_id(event) == MS_RIGHT && item &&
  643. X    (item == read_item ||
  644. X    (item == sub_hdr_item[0] || item == sub_hdr_item[1]))) {
  645. X    (void) help(0, "next", tool_help);
  646. X    return;
  647. X    }
  648. X    if (item && (item == sub_hdr_item[4] || item == sub_hdr_item[5])) {
  649. X    (void) help(0, "Menu Read", tool_help);
  650. X    return;
  651. X    }
  652. X    if (!msg_cnt) {
  653. X    wprint ("No Mail.\n");
  654. X    return;
  655. X    }
  656. X    if (item && item == read_item || ison(msg[current_msg].m_flags, DELETE))
  657. X    (void) next_msg();
  658. X    if (this_msg != current_msg || ison(msg[current_msg].m_flags, UNREAD) ||
  659. X        (current_msg < n_array[0] || current_msg > n_array[screen])) {
  660. X    set_isread(current_msg);
  661. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  662. X    }
  663. X    if (isoff(msg[current_msg].m_flags, DELETE))
  664. X    display_msg(current_msg, (u_long)0);
  665. }
  666. X
  667. /* the panel button that says "filename" and "directory", etc... text item */
  668. Panel_setting
  669. file_dir(item, event)
  670. Panel_item item;
  671. Event *event;
  672. {
  673. X    register char *p;
  674. X    u_long bang = ison(glob_flags, IGN_BANG);
  675. X    char buf[MAXPATHLEN];
  676. X
  677. X    if (event_id(event) == ESC) {
  678. X    /* file expansion request */
  679. X    int n;
  680. X    char **files;
  681. X    p = panel_get_value(item);
  682. X    (void) sprintf(buf, "%s*", p);
  683. X    timeout_cursors(1);
  684. X    if ((n = filexp(buf, &files)) > 0) {
  685. X        Debug("%d: ",n), print_argv(files);
  686. X        if (n > 1) {
  687. X        n = lcprefix(files, 0);
  688. X        files[0][n] = 0;
  689. X        }
  690. X        panel_set_value(item, trim_filename(files[0]));
  691. X        free_vec(files);
  692. X    } else
  693. X        errbell(n);    /* see curs_io.c */
  694. X    timeout_cursors(0);
  695. X    return PANEL_NONE;
  696. X    }
  697. X
  698. X    if (item == folder_text_item) {
  699. X    (void) sprintf(buf, "folder %s %s",
  700. X        (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) &&
  701. X        !ask("Folder has been modified.  Update changes?"))? "!" : "",
  702. X        panel_get_value(folder_text_item));
  703. X    }
  704. X    else if (item == file_item) {
  705. X    register char *b = buf;
  706. X    char msgstr[BUFSIZ];
  707. X
  708. X    if (event_id(event) == '\n' || event_id(event) == '\r')
  709. X        b += Strcpy(buf, "save  ");
  710. X    else
  711. X        b += Strcpy(buf, "write ");
  712. X    if ((p = panel_get_value(msg_num_item)) && *p)
  713. X        b += Strcpy(b, p);
  714. X    else {
  715. X        if (ison(msg[current_msg].m_flags, DELETE) &&
  716. X            !do_set(set_options, "show_deleted")) {
  717. X        (void) sprintf(msgstr, "Message %d deleted -- save anyway?",
  718. X                        current_msg+1);
  719. X        if (ask(msgstr) != TRUE) {
  720. X            wprint("Message not saved\n");
  721. X            return PANEL_NONE;
  722. X        }
  723. X        }
  724. X        b += strlen(sprintf(b, "%d", current_msg+1));
  725. X    }
  726. X    *b++ = ' ', *b = 0;
  727. X    if (!(p = panel_get_value(item)) || !*p &&
  728. X        (!(p = do_set(set_options, "mbox")) || !*p))
  729. X        p = DEF_MBOX;
  730. X    if (chk_option("verify", "save")) {
  731. X        (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p));
  732. X        if (ask(msgstr) != TRUE) {
  733. X        wprint("Message not saved\n");
  734. X        return PANEL_NONE;
  735. X        }
  736. X    }
  737. X    (void) strcpy(b, p); /* now add to command */
  738. X    }
  739. X    turnon(glob_flags, IGN_BANG);
  740. X    (void) cmd_line(buf, msg_list);
  741. X    if (!bang)
  742. X    turnoff(glob_flags, IGN_BANG);
  743. X    return PANEL_NONE;
  744. }
  745. X
  746. #ifndef NO_WALK_MENUS
  747. void
  748. xx_file_dir(item, value)
  749. Panel_item item;
  750. char * value;
  751. {
  752. X    char buf[BUFSIZ];
  753. X    u_long bang = ison(glob_flags, IGN_BANG);
  754. X
  755. X    if (item == folder_item) {
  756. X    (void) sprintf(buf, "folder %s ",
  757. X        (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) &&
  758. X        !ask("Folder has been modified.  Update changes?"))? "!" : "");
  759. X    strcat(buf, value);
  760. X    } else if (item == save_item) {
  761. X    char msgstr[BUFSIZ], *p;
  762. X    register char *p2 = (char *)panel_get_value(msg_num_item);
  763. X    (void) strcpy(buf, "save ");
  764. X
  765. X    if (p2 && *p2) {
  766. X        (void) strcat(buf, p2);
  767. X        (void) strcat(buf, " ");
  768. X    }
  769. X    (void) strcat(buf, value);
  770. X    if (chk_option("verify", "save")) {
  771. X        (void) sprintf(msgstr, "Save in %s? ", trim_filename(value));
  772. X        if (ask(msgstr) != TRUE) {
  773. X        wprint("Message not saved\n");
  774. X        return;
  775. X        }
  776. X    }
  777. X    }
  778. X    turnon(glob_flags, IGN_BANG);
  779. X    (void) cmd_line(buf, msg_list);
  780. X    if (!bang)
  781. X    turnoff(glob_flags, IGN_BANG);
  782. X    (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  783. }
  784. X
  785. /*
  786. X * callback routine for the panel items that need filename input.
  787. X * (folder and save)
  788. X */
  789. void
  790. do_file_dir(item, event)
  791. Panel_item item;
  792. Event *event;
  793. {
  794. X    if (item == folder_item) {
  795. X    char *p = panel_get_value(folder_text_item);
  796. X    if (!*p) {
  797. X        ok_box("Enter folder name.");
  798. X        return;
  799. X    }
  800. X    xx_file_dir(item, p);
  801. X    } else if (item == save_item) {
  802. X    if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) {
  803. X        event_id(event) = '\n';  /* let file_dir think it got a \n */
  804. X        file_dir(file_item, event);
  805. X        return;
  806. X    }
  807. X    }
  808. X    (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  809. }
  810. #else /* NO_WALK_MENUS */
  811. X
  812. /*
  813. X * callback routine for the panel items that need filename input.
  814. X * (folder and save)
  815. X */
  816. void
  817. do_file_dir(item, value, event)
  818. Panel_item item;
  819. int value;
  820. Event *event;
  821. {
  822. X    char buf[BUFSIZ];
  823. X    u_long bang = ison(glob_flags, IGN_BANG);
  824. X
  825. X    if (item == folder_item) {
  826. X    (void) sprintf(buf, "folder %s ",
  827. X        (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) &&
  828. X        !ask("Folder has been modified.  Update changes?"))? "!" : "");
  829. X    if (event_id(event) == MS_LEFT) {
  830. X        char *p = panel_get_value(folder_text_item);
  831. X        if (!*p) {
  832. X        ok_box("Enter folder name.");
  833. X        return;
  834. X        }
  835. X        (void) strcat(buf, p);
  836. X    } else if (!value)
  837. X        (void) strcat(buf, "%");
  838. X    else if (value == 1)
  839. X        (void) strcat(buf, "&");
  840. X    else if (value == 2)
  841. X        (void) strcat(buf, "#");
  842. X    else
  843. X        (void) strcat(buf, panel_get(item, PANEL_CHOICE_STRING, value));
  844. X    } else if (item == save_item) {
  845. X    char msgstr[BUFSIZ], *p;
  846. X    (void) strcpy(buf, "save ");
  847. X    if (event_id(event) == MS_LEFT) {
  848. X        if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) {
  849. X        event_id(event) = '\n';  /* let file_dir think it got a \n */
  850. X        file_dir(file_item, event);
  851. X        return;
  852. X        }
  853. X    } else if (value == 0) {
  854. X        register char *p2 = (char *)panel_get_value(msg_num_item);
  855. X
  856. X        if (!(p = do_set(set_options, "mbox")) || !*p)
  857. X        p = DEF_MBOX;
  858. X        if (p2 && *p2) {
  859. X        (void) strcat(buf, p2);
  860. X        (void) strcat(buf, " ");
  861. X        }
  862. X        (void) strcat(buf, p);
  863. X    } else
  864. X        (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value));
  865. X    if (chk_option("verify", "save")) {
  866. X        (void) sprintf(msgstr, "Save in %s? ", trim_filename(p));
  867. X        if (ask(msgstr) != TRUE) {
  868. X        wprint("Message not saved\n");
  869. X        return;
  870. X        }
  871. X    }
  872. X    }
  873. X    turnon(glob_flags, IGN_BANG);
  874. X    (void) cmd_line(buf, msg_list);
  875. X    if (!bang)
  876. X    turnoff(glob_flags, IGN_BANG);
  877. X    (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  878. }
  879. #endif /* NO_WALK_MENUS */
  880. X
  881. /*ARGSUSED*/
  882. void
  883. do_help(item, value, event)
  884. Panel_item item;
  885. register int value;
  886. Event *event;
  887. {
  888. X    register char *p, *helpfile = tool_help;
  889. X    if (!event || event_id(event) == MS_LEFT)
  890. X    value = 0;
  891. X    switch(value) {
  892. X    case 0: p = "about", helpfile = cmd_help;
  893. X    when 1: p = "help";
  894. X    when 2: p = "mouse";
  895. X    when 3: p = "windows";
  896. X    when 4: p = "hdr_format", helpfile = cmd_help;
  897. X    when 5: p = "msg_list", helpfile = cmd_help;
  898. X    when 6: p = "folder";
  899. X    otherwise: p = "general";
  900. X    }
  901. X    (void) help(0, p, helpfile);
  902. }
  903. X
  904. /*ARGSUSED*/
  905. void
  906. do_update(item, value, event)
  907. Panel_item item;
  908. int value;
  909. Event *event;
  910. {
  911. X    char *argv[2];
  912. X    if (event && event_id(event) != MS_LEFT) {
  913. X    if (value == 0) {
  914. X        if (check_new_mail() == 0)
  915. X        print("No new mail.\n");
  916. X    } else
  917. X        (void) help(0, "update", tool_help);
  918. X    return;
  919. X    }
  920. X    argv[0] = "update";
  921. X    argv[1] = NULL;
  922. X    timeout_cursors(TRUE);
  923. X    (void) folder(0, argv, NULL);
  924. X    timeout_cursors(FALSE);
  925. }
  926. X
  927. /*ARGSUSED*/
  928. void
  929. toolquit(item, value, event)
  930. Panel_item item;
  931. int value;
  932. Event *event;
  933. {
  934. X    void wmgr_changestate(), wmgr_changelevel();
  935. X    register int which;
  936. X
  937. X    if (!value || event_id(event) == MS_LEFT) {
  938. X    if (ison(glob_flags, DO_UPDATE)) {
  939. X        do_update(NO_ITEM, 0, NO_EVENT);
  940. X        turnoff(glob_flags, NEW_MAIL);
  941. X    }
  942. X    check_icons();
  943. X    mail_status(0); /* lower flag (if up) print current num of msgs */
  944. X    /* wmgr_changestate (window_get(tool, WIN_FD), rootfd, TRUE); */
  945. X    /* wmgr_changelevel (window_get(tool, WIN_FD), parentfd, TRUE); */
  946. X    close_frame();
  947. X    window_set(tool, FRAME_CLOSED, TRUE, NULL);
  948. X    is_iconic = ((int) window_get(tool, FRAME_CLOSED));
  949. X    return;
  950. X    } else if (value == 2) {
  951. X    (void) help(0, "quit", tool_help);
  952. X    return;
  953. X    }
  954. X    /* modify this to check for "abort" choice when ternary return values
  955. X     * are possible!
  956. X     */
  957. X    if (isoff(glob_flags, DO_UPDATE) ||
  958. X        ask("Folder has been modified -- update?")) {
  959. X    if (!copyback("Quit anyway?", TRUE))
  960. X        return;
  961. X    }
  962. X    cleanup(0);
  963. }
  964. X
  965. /*ARGSUSED*/
  966. void
  967. do_mark(item, value, event)
  968. Panel_item item;
  969. int value;
  970. Event *event;
  971. {
  972. X    if (event && (event_id(event) == MS_LEFT) || value == 0) {
  973. X    int msg_num = event? current_msg : (int)item;
  974. X    /* mark message */
  975. X    if (ison(msg[msg_num].m_flags, M_PRIORITY(0)))
  976. X        turnoff(msg[msg_num].m_flags, M_PRIORITY(0));
  977. X    else
  978. X        turnon(msg[msg_num].m_flags, M_PRIORITY(0));
  979. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  980. X    } else if (value < 7) {
  981. X    /* set priority */
  982. X    char buf[90];
  983. X    (void) cmd_line(sprintf(buf, "mark -%c %s",
  984. X        value < 6? value + 'A' - 1 : ' ',
  985. X        panel_get_value(msg_num_item)), NULL);
  986. X    } else
  987. X    (void) help(0, "mark", tool_help);
  988. X    if (value != 7 && item)
  989. X    panel_set_value(item, 0);
  990. }
  991. X
  992. /*ARGSUSED*/
  993. void
  994. do_lpr(item, value, event)
  995. Panel_item item;
  996. int value;
  997. Event *event;
  998. {
  999. X    char buf[128];
  1000. X
  1001. X    if (event && (event_id(event) == MS_LEFT)) {
  1002. X    wprint("Sending message %d to printer...\n", current_msg+1);
  1003. X    (void) strcpy(buf, "lpr ");
  1004. X    if (value)
  1005. X        (void) sprintf(buf, "lpr \"%s\"", panel_get_value(msg_num_item));
  1006. X    timeout_cursors(TRUE);
  1007. X    (void) cmd_line(buf, msg_list);
  1008. X    timeout_cursors(FALSE);
  1009. X    } else
  1010. X    (void) help(0, "printer", tool_help);
  1011. }
  1012. X
  1013. /* panel selection button pressed to send a letter.
  1014. X * we've attached the sign panel item to this item to 1) avoid
  1015. X * using a global and 2) make it general enough so that multiple
  1016. X * compose windows can have multiple send_items and we can
  1017. X * identify which sign/fortune items are associated with this
  1018. X * particular letter.  The fortune item is attached to the sign
  1019. X * item.
  1020. X */
  1021. /*ARGSUSED*/
  1022. void
  1023. do_send(item, value, event)
  1024. Panel_item item;
  1025. int value;
  1026. register Event *event;
  1027. {
  1028. X    Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL);
  1029. X    Panel_item sign_item = (Panel_item)panel_get(item, PANEL_CLIENT_DATA);
  1030. X    Panel_item fortune_item =
  1031. X    (Panel_item)panel_get(sign_item, PANEL_CLIENT_DATA);
  1032. X    Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
  1033. X    char *argv[5], buf[64];
  1034. X    char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
  1035. X    char *p, *oldsign = NULL, *oldfortune = NULL;
  1036. X
  1037. X    if (textsw_store_file(textsw, file, 0, 0)) {
  1038. X    error("Can't save to %s", file);
  1039. X    return;
  1040. X    }
  1041. X    /* check if user changed variables before sending */
  1042. X    if (p = do_set(set_options, "autosign"))
  1043. X    oldsign = savestr(p);
  1044. X    if (panel_get_value(sign_item) && !oldsign)
  1045. X    cmd_line(strcpy(buf, "\\set autosign"), NULL);
  1046. X    else if (!panel_get_value(sign_item) && oldsign)
  1047. X    cmd_line(strcpy(buf, "\\unset autosign"), NULL);
  1048. X    if (p = do_set(set_options, "fortune"))
  1049. X    oldfortune = savestr(p);
  1050. X    if (panel_get_value(fortune_item) && !oldfortune)
  1051. X    (void) cmd_line(strcpy(buf, "\\set fortune"), NULL);
  1052. X    else if (!panel_get_value(fortune_item) && oldfortune)
  1053. X    (void) cmd_line(strcpy(buf, "\\unset fortune"), NULL);
  1054. X    turnoff(glob_flags, IS_GETTING);
  1055. X    argv[0] = "mail";
  1056. X    argv[1] = "-Uh";
  1057. X    argv[2] = file;
  1058. X    argv[3] = NULL;
  1059. X    clear_msg_list(msg_list);
  1060. X    timeout_cursors(TRUE);
  1061. X    if (do_mail(3, argv, msg_list) == 0) {
  1062. X    (void) unlink(file);
  1063. X    set_comp_items(panel);
  1064. X    }
  1065. X    if (panel_get_value(sign_item) && !oldsign)
  1066. X    (void) cmd_line(strcpy(buf, "\\unset autosign"), NULL);
  1067. X    else if (!panel_get_value(sign_item) && oldsign) {
  1068. X    argv[0] = "set";
  1069. X    argv[1] = "autosign";
  1070. X    if (*oldsign) {
  1071. X        argv[2] = "=";
  1072. X        argv[3] = oldsign;
  1073. X        argv[4] = NULL;
  1074. X        (void) set(4, argv, NULL);
  1075. X    } else {
  1076. X        argv[2] = NULL;
  1077. X        (void) set(2, argv, NULL);
  1078. X    }
  1079. X    }
  1080. X    if (panel_get_value(fortune_item) && !oldfortune)
  1081. X    cmd_line(strcpy(buf, "\\unset fortune"), NULL);
  1082. X    else if (!panel_get_value(fortune_item) && oldfortune) {
  1083. X    argv[0] = "set";
  1084. X    argv[1] = "fortune";
  1085. X    if (*oldfortune) {
  1086. X        argv[2] = "=";
  1087. X        argv[3] = oldfortune;
  1088. X        argv[4] = NULL;
  1089. X        (void) set(4, argv, NULL);
  1090. X    } else {
  1091. X        argv[2] = NULL;
  1092. X        (void) set(2, argv, NULL);
  1093. X    }
  1094. X    }
  1095. X    xfree(oldsign), xfree(oldfortune);
  1096. X    timeout_cursors(FALSE);
  1097. }
  1098. X
  1099. /*ARGSUSED*/
  1100. void
  1101. do_include(item, value, event)
  1102. Panel_item item;
  1103. int value;
  1104. Event *event;
  1105. {
  1106. X    extern FILE *ed_fp;
  1107. X    char *p, buf[64], *file;
  1108. X    Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL),
  1109. X    PANEL_CLIENT_DATA);
  1110. X
  1111. X    if (event && event_id(event) == MS_LEFT)
  1112. X    value = 0;
  1113. X    if (value == 2) {
  1114. X    (void) help(0, "include", tool_help);
  1115. X    return;
  1116. X    }
  1117. X    p = panel_get_value(msg_num_item);
  1118. X    (void) sprintf(buf, "%c%c%s", *escape, value == 0? 'i' : 'f', p? p : "");
  1119. X
  1120. X    file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
  1121. X    if (textsw_store_file(textsw, file, 0, 0)) {
  1122. X    (void) ask("Something's wrong... Click anything.");
  1123. X    return;
  1124. X    }
  1125. X    if (ed_fp) {
  1126. X    (void) ask("tmpfile already in use... Click anything.");
  1127. X    (void) fclose(ed_fp);
  1128. X    }
  1129. X    if (!(ed_fp = mask_fopen(file, "a"))) {
  1130. X    error("Cannot open %s to append msg.", file);
  1131. X    return;
  1132. X    }
  1133. X    (void) add_to_letter(buf);
  1134. X    (void) fclose(ed_fp), ed_fp = NULL_FILE;
  1135. #ifdef SUN_4_0 /* SunOS 4.0+ */
  1136. X    window_set(textsw, TEXTSW_FILE_CONTENTS, file, NULL);
  1137. #else /* SUN_4_0 */
  1138. X    textsw_load_file(textsw, file, 1, 0, 0);
  1139. #endif /* SUN_4_0 */
  1140. X    window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL);
  1141. X    (void) unlink(file);
  1142. }
  1143. X
  1144. /*ARGSUSED*/
  1145. void
  1146. do_compose(item, value, event)
  1147. Panel_item item;
  1148. int value;
  1149. Event *event;
  1150. {
  1151. X    char buf[5];
  1152. X
  1153. X    if (event && event_id(event) != MS_LEFT) {
  1154. X    (void) help(0, "compose", tool_help);
  1155. X    return;
  1156. X    }
  1157. X    open_compose();
  1158. X    if (!compose_frame)
  1159. X    return;    /* open failed */
  1160. X    clear_msg_list(msg_list);
  1161. X    if (do_mail(0, DUBL_NULL, msg_list) == 0) {
  1162. X    Panel panel = get_compose_panel();
  1163. X    Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
  1164. X    start_textsw_edit(textsw, TRUE);
  1165. X    set_comp_items(panel);
  1166. X    }
  1167. }
  1168. X
  1169. /*
  1170. X * notify proc for reply button -- also called from select.c (do_menu()) ,
  1171. X * in which case "event" is null and "value" contains the message
  1172. X * number of the message to reply to.
  1173. X */
  1174. /*ARGSUSED*/
  1175. void
  1176. respond_mail(item, value, event)
  1177. Panel_item item;
  1178. int value;
  1179. Event *event;
  1180. {
  1181. X    int tmp = current_msg;
  1182. X    char buf[256];
  1183. X
  1184. X    if (event && event_id(event) == MS_LEFT)
  1185. X    value = 0;
  1186. X    if (event && value == 4) {
  1187. X    (void) help(0, "respond", tool_help);
  1188. X    return;
  1189. X    }
  1190. X    if (!msg_cnt) {
  1191. X    wprint("No messages to respond to.\n");
  1192. X    return;
  1193. X    }
  1194. X    if (ison(glob_flags, IS_GETTING)) {
  1195. X    wprint("Finish editing current message first.\n");
  1196. X    return;
  1197. X    }
  1198. X    if (!event)
  1199. X    tmp = value, value = 0;
  1200. X    open_compose();
  1201. X    if (!compose_frame)
  1202. X    return;    /* open failed */
  1203. X    (void) sprintf(buf, "%s %s %d",
  1204. X    (value == 2 || value == 3)? "\\replyall" : "\\replysender",
  1205. X    (value == 1 || value == 3)? "-i": NO_STRING, tmp+1);
  1206. X    if (cmd_line(buf, NULL) != -1) {
  1207. X    Panel panel = get_compose_panel();
  1208. X    Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
  1209. X    wprint("Responding to message %d\n", tmp+1);
  1210. X    start_textsw_edit(textsw, FALSE);
  1211. X    set_comp_items(panel);
  1212. X    }
  1213. }
  1214. X
  1215. /*ARGSUSED*/
  1216. void
  1217. load_from_file(item, value, event)
  1218. Panel_item item;
  1219. int value;
  1220. Event *event;
  1221. {
  1222. X    int x = 0;
  1223. X    Textsw textsw;
  1224. X    Panel_item filename_item = (Panel_item)panel_get(item, PANEL_CLIENT_DATA);
  1225. X    char *file, *p = panel_get_value(filename_item);
  1226. #ifndef SUN_4_0 /* SunOS 4.0+ */
  1227. X    char *sfile, buf[128];
  1228. X    extern FILE *ed_fp;
  1229. #endif /* SUN_4_0 */
  1230. X    
  1231. X    if (!*p) {
  1232. X    wprint("Specify Filename.\n");
  1233. X    return;
  1234. X    }
  1235. X    file = getpath(p, &x);
  1236. X    if (x == 1)
  1237. X    wprint("%s: is a directory.\n", p);
  1238. X    else if (x == -1)
  1239. X    wprint("%s: %s\n", p, file);
  1240. X    if (x)
  1241. X    return;
  1242. X    timeout_cursors(TRUE);
  1243. X    textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL),
  1244. X    PANEL_CLIENT_DATA);
  1245. X    if (event_id(event) != MS_LEFT && value == 1)
  1246. X    /* replace */
  1247. X    textsw_load_file(textsw, file, 1, 0, 0);
  1248. X    else {
  1249. X    /* insert */
  1250. #ifdef SUN_4_0 /* SunOS 4.0+ */
  1251. X    window_set(textsw, TEXTSW_INSERT_FROM_FILE, file, NULL);
  1252. #else /* SUN_4_0 */
  1253. X    /* best we can do with pre 4.0 is save the current file
  1254. X     * and append the new file onto the end.
  1255. X     */
  1256. X    sfile = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
  1257. X    if (textsw_store_file(textsw, sfile, 0, 0)) {
  1258. X        (void) ask("Can't save file... Click anything.");
  1259. X        return;
  1260. X    }
  1261. X    if (ed_fp) {
  1262. X        (void) ask("tmpfile already in use... Click anything.");
  1263. X        fclose(ed_fp);
  1264. X    }
  1265. X    if (!(ed_fp = mask_fopen(sfile, "a"))) {
  1266. X        error("Cannot open %s.", sfile);
  1267. X        return;
  1268. X    }
  1269. X    (void) sprintf(buf, "%c%c%s", *escape, 'r', trim_filename(p));
  1270. X    (void) add_to_letter(buf);
  1271. X    (void) fclose(ed_fp), ed_fp = NULL_FILE;
  1272. X    textsw_load_file(textsw, sfile, 1, 0, 0);
  1273. X    (void) unlink(sfile);
  1274. #endif /* SUN_4_0 */
  1275. X    }
  1276. X    window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL);
  1277. X    panel_set_value(item, 0);
  1278. X    timeout_cursors(FALSE);
  1279. }
  1280. X
  1281. /*ARGSUSED*/
  1282. void
  1283. save_to_file(item, value, event)
  1284. Panel_item item;
  1285. Event *event;
  1286. {
  1287. X    Panel_item filename_item = panel_get(item, PANEL_CLIENT_DATA);
  1288. X    char *file = panel_get_value(filename_item);
  1289. X    FILE *fp;
  1290. X    Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL),
  1291. X    PANEL_CLIENT_DATA);
  1292. X
  1293. X    if (!*file) {
  1294. X    wprint("Specify Filename\n");
  1295. X    return;
  1296. X    }
  1297. X    timeout_cursors(TRUE);
  1298. X    /* append to file -- no confirmation necessary */
  1299. X    if (fp = open_file(file, FALSE, TRUE)) {
  1300. X    char buf[BUFSIZ];
  1301. X    Textsw_index next_pos = 0, tmp;
  1302. X    Textsw_index length =
  1303. X        (Textsw_index)window_get(textsw, TEXTSW_LENGTH);
  1304. X    do  {
  1305. X        tmp = next_pos;
  1306. X        next_pos = (Textsw_index) window_get(textsw, TEXTSW_CONTENTS,
  1307. X        next_pos, buf, sizeof(buf));
  1308. X        if (fwrite(buf, sizeof(char), (int)(next_pos - tmp), fp) == 0)
  1309. X        error("%s may be incomplete", file);
  1310. X    } while (next_pos < length);
  1311. X    (void) close_lock(file, fp);
  1312. X    wprint("Wrote %d bytes to %s\n", length, trim_filename(file));
  1313. X    }
  1314. X    timeout_cursors(FALSE);
  1315. }
  1316. X
  1317. void
  1318. abort_mail(item, event)
  1319. Panel_item item;
  1320. Event *event;
  1321. {
  1322. X    Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL);
  1323. X    Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
  1324. X    wprint("Aborted letter.\n");
  1325. X    textsw_reset(textsw, 0, 0);
  1326. X    rm_edfile(0);
  1327. X    set_comp_items(panel);
  1328. }
  1329. X
  1330. /* set the compose panel items */
  1331. void
  1332. set_comp_items(panel)
  1333. Panel panel;
  1334. {
  1335. X    Panel_item item, next;
  1336. X    Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
  1337. X    int getting = ison(glob_flags, IS_GETTING) != 0;
  1338. X    int i = 0;
  1339. X
  1340. X    window_set(textsw, TEXTSW_READ_ONLY, !getting, NULL);
  1341. X    /* remove next line when multiple composes become a reality */
  1342. X    (void) panel_set(reply_item, PANEL_SHOW_ITEM, !getting, NULL);
  1343. X    /* skip "close" item */
  1344. X    item = (Panel_item) panel_get(panel, PANEL_FIRST_ITEM);
  1345. X    for (item = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
  1346. X    item; item = next) {
  1347. X    next = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
  1348. X    (void) panel_set(item,
  1349. X        PANEL_SHOW_ITEM, (i++ < 1)? !getting : getting, NULL);
  1350. X    }
  1351. }
  1352. X
  1353. /*
  1354. X * Ask a yes/no question and return an answer: TRUE or FALSE.
  1355. X */
  1356. ask(question)
  1357. char *question;
  1358. {
  1359. #ifdef SUN_4_0 /* SunOS 4.0+ */
  1360. X    return alert_prompt(tool, (Event *)NULL,
  1361. X    ALERT_MESSAGE_STRINGS,    question, NULL,
  1362. X    ALERT_BUTTON_YES,    "Yes",
  1363. X    ALERT_BUTTON_NO,    "No",
  1364. X    NULL) == ALERT_YES;
  1365. #else /* SUN_4_0 */
  1366. X    Event event;
  1367. X    struct prompt prompt;
  1368. X    Rect *rect = (Rect *)window_get(tool, WIN_RECT);
  1369. X    char buf[MAXPATHLEN];
  1370. X
  1371. X    (void) sprintf(buf,
  1372. X        "%s  \nPress LEFT Button to Confirm.  Anything else to cancel.",
  1373. X        question);
  1374. X    prompt.prt_rect.r_left = rect->r_left + (rect->r_width / 3);
  1375. X    prompt.prt_rect.r_top = rect->r_top + (rect->r_height / 3);
  1376. X    prompt.prt_rect.r_width = prompt.prt_rect.r_height = PROMPT_FLEXIBLE;
  1377. X    prompt.prt_font = mush_font;
  1378. X    prompt.prt_text = buf;
  1379. X
  1380. X    menu_prompt(&prompt, &event, window_get(tool, WIN_FD));
  1381. X    return event_id(&event) == MS_LEFT;
  1382. #endif /* SUN_4_0 */
  1383. }
  1384. X
  1385. void
  1386. ok_box(buf)
  1387. char *buf;
  1388. {
  1389. #ifdef SUN_4_0
  1390. X    (void) alert_prompt(tool, (Event *)NULL,
  1391. X    ALERT_MESSAGE_STRINGS,    buf, NULL,
  1392. X    ALERT_BUTTON_YES,        "Ok",
  1393. X    NULL);
  1394. #else /* SUN_4_0 */
  1395. X    Event event;
  1396. X    struct prompt prompt;
  1397. X    Rect *rect = (Rect *)window_get(tool, WIN_RECT);
  1398. X    (void) strcat(buf, "  \nPress LEFT Button to Continue.");
  1399. X    prompt.prt_rect.r_left = rect->r_left + (rect->r_width / 3);
  1400. X    prompt.prt_rect.r_top = rect->r_top + (rect->r_height / 3);
  1401. X    prompt.prt_rect.r_width = prompt.prt_rect.r_height = PROMPT_FLEXIBLE;
  1402. X    prompt.prt_font = mush_font;
  1403. X    prompt.prt_text = buf;
  1404. X    menu_prompt(&prompt, &event, window_get(tool, WIN_FD));
  1405. #endif /* SUN_4_0 */
  1406. }
  1407. X
  1408. Panel_setting
  1409. msg_num_done(item, event)
  1410. Panel_item item;
  1411. Event *event;
  1412. {
  1413. X    char buf[82];
  1414. X    u_long bang = ison(glob_flags, IGN_BANG);
  1415. X    register char *p;
  1416. X    int n;
  1417. X
  1418. X    if (event_id(event) != '\n' && event_id(event) != '\r') {
  1419. X    (void) help(0, "message range", tool_help);
  1420. X    return PANEL_NONE;
  1421. X    }
  1422. X    (void) sprintf(buf, "headers %s", (p = (char *)panel_get_value(item)));
  1423. X    (void) panel_set(item, PANEL_VALUE, NO_STRING, NULL);
  1424. X    if (!(n = chk_msg(p)))
  1425. X    return PANEL_NONE;
  1426. X    current_msg = --n;
  1427. X    turnon(glob_flags, IGN_BANG);
  1428. X    (void) cmd_line(buf, msg_list);
  1429. X    if (!bang)
  1430. X    turnoff(glob_flags, IGN_BANG);
  1431. X    (void) display_msg(n, (u_long)0);
  1432. X    return PANEL_NONE;
  1433. }
  1434. X
  1435. void
  1436. do_sort(item, value, event)
  1437. Panel_item item;
  1438. int value;
  1439. Event *event;
  1440. {
  1441. X    char *argv[3], list[MAXMSGS_BITS];
  1442. X    char *p = (char *)panel_get_value(msg_num_item);
  1443. X    int n = 0;
  1444. X
  1445. X    if (p && *p) {
  1446. X    argv[0] = p;
  1447. X    argv[1] = NULL;
  1448. X    n = get_msg_list(argv, list);
  1449. X    }
  1450. X    argv[0] = "sort";
  1451. X    argv[2] = NULL;
  1452. X
  1453. X    if (event_id(event) == MS_LEFT)
  1454. X    value = 0;
  1455. X    switch(value) {
  1456. X    case 0: argv[1] = "S";
  1457. X    when 1: argv[1] = "a";
  1458. X    when 2: argv[1] = "l";
  1459. X    when 3: argv[1] = "R";
  1460. X    when 4: argv[1] = "s";
  1461. X    when 5: argv[1] = "d";
  1462. X    when 6: argv[1] = "p";
  1463. X    when 7: do_set(set_options, "sort");
  1464. X    when 8: (void) help(0, "sort", tool_help);
  1465. X    }
  1466. X    if (value != 8) {
  1467. X    if (n > 0) {
  1468. X        turnon(glob_flags, IS_PIPE);
  1469. X        (void) sort(2, argv, list);
  1470. X        turnoff(glob_flags, IS_PIPE);
  1471. X    } else
  1472. X        (void) sort(2, argv, NULL);
  1473. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  1474. X    }
  1475. X    (void) panel_set(item, PANEL_VALUE, 0, NULL);
  1476. }
  1477. X
  1478. void
  1479. do_options(item, value, event)
  1480. Panel_item item;
  1481. int value;
  1482. Event *event;
  1483. {
  1484. X    if (event_id(event) == MS_LEFT) {
  1485. X    view_options();
  1486. X    return;
  1487. X    }
  1488. X    switch (value) {
  1489. X    case 0:
  1490. X        view_options();
  1491. X    when 1:
  1492. X        do_ignore();
  1493. X    when 2:
  1494. X        do_aliases();
  1495. X    }
  1496. }
  1497. SHAR_EOF
  1498. chmod 0644 doproc.c ||
  1499. echo 'restore of doproc.c failed'
  1500. Wc_c="`wc -c < 'doproc.c'`"
  1501. test 24153 -eq "$Wc_c" ||
  1502.     echo 'doproc.c: original size 24153, current size' "$Wc_c"
  1503. rm -f _shar_wnt_.tmp
  1504. fi
  1505. # ============= execute.c ==============
  1506. if test -f 'execute.c' -a X"$1" != X"-c"; then
  1507.     echo 'x - skipping execute.c (File already exists)'
  1508.     rm -f _shar_wnt_.tmp
  1509. else
  1510. > _shar_wnt_.tmp
  1511. echo 'x - extracting execute.c (Text)'
  1512. sed 's/^X//' << 'SHAR_EOF' > 'execute.c' &&
  1513. /* execute.c     (c) copyright    10/28/86 (Dan Heller) */
  1514. X
  1515. #include "mush.h"
  1516. #ifdef BSD
  1517. #include <sys/wait.h>
  1518. #else
  1519. #ifndef SYSV
  1520. #include <wait.h>
  1521. #endif /* SYSV */
  1522. #endif /* BSD */
  1523. X
  1524. #ifdef lint
  1525. #include <sys/resource.h>
  1526. #endif /* lint */
  1527. X
  1528. static jmp_buf execjbuf;
  1529. X
  1530. #ifdef SUNTOOL
  1531. X
  1532. /*ARGSUSED*/
  1533. Notify_value
  1534. my_wait3(tty, pid, status, rusage)
  1535. Tty tty;
  1536. int pid;
  1537. union wait *status;
  1538. struct rusage *rusage;
  1539. {
  1540. X    extern Panel_item edit_item;
  1541. X    Textsw textsw = (Textsw)window_get(tty, WIN_CLIENT_DATA);
  1542. X    char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
  1543. X    int i = 0;
  1544. X
  1545. X    if (WIFSTOPPED(*status)) {
  1546. X    kill(pid, SIGCONT);
  1547. X    return (NOTIFY_IGNORED);
  1548. X    }
  1549. X    if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */
  1550. X    return NOTIFY_DONE;
  1551. X    /* editor died -- reset exec_pid so no one thinks we're running */
  1552. X    exec_pid = 0;
  1553. X    (void) window_set(tty, TTY_ARGV, TTY_ARGV_DO_NOT_FORK, NULL);
  1554. X    wprint("Editor done.\n");
  1555. X    (void) window_set(tty_sw, WIN_SHOW, FALSE, NULL);
  1556. #ifdef SUN_4_0 /* SunOS 4.0+ */
  1557. X    (void) window_set(textsw,
  1558. X    WIN_SHOW,        TRUE,
  1559. X    TEXTSW_FILE_CONTENTS,    file,
  1560. X    NULL);
  1561. #else /* SUN_4_0 */
  1562. X    textsw_load_file(textsw, file, 1, 0, 0);
  1563. X    textsw_set(textsw, WIN_SHOW, TRUE, NULL);
  1564. #endif /* SUN_4_0 */
  1565. X    textsw_normalize_view(textsw, (Textsw_index)0);
  1566. X    (void) unlink(file);
  1567. X    set_comp_items(panel_get(edit_item, PANEL_PARENT_PANEL));
  1568. X
  1569. X    return NOTIFY_DONE;
  1570. }
  1571. X
  1572. tool_edit_letter(textsw, argv)
  1573. Textsw textsw;
  1574. char **argv;
  1575. {
  1576. X    Rect *msg_rect = (Rect *)window_get(textsw, WIN_RECT);
  1577. X
  1578. X    wprint("Starting \"%s\"...\n", *argv);
  1579. #ifdef SUN_4_0
  1580. X    window_set(textsw, WIN_SHOW, FALSE, NULL);
  1581. #else /* SUN_4_0 */
  1582. X    textsw_set(textsw, WIN_SHOW, FALSE, NULL);
  1583. #endif /* SUN_4_0 */
  1584. X    ttysw_output(tty_sw, "\f", 1);  /* clear screen */
  1585. X    (void) window_set(tty_sw,
  1586. X    WIN_RECT,    msg_rect,
  1587. X    TTY_ARGV,    argv,
  1588. X    WIN_SHOW,    TRUE,
  1589. X    NULL);
  1590. X    if ((exec_pid = (int) window_get(tty_sw, TTY_PID)) == -1) {
  1591. X    error("Couldn't execute %s", *argv);
  1592. X    return -1;
  1593. X    }
  1594. X    notify_set_wait3_func(tty_sw, my_wait3, exec_pid);
  1595. X    Debug("tty pid = %d\n", exec_pid);
  1596. X    return 0;
  1597. }
  1598. #endif /* SUNTOOL */
  1599. X
  1600. execute(argv)
  1601. char **argv;
  1602. {
  1603. #ifdef SYSV
  1604. X    int status;
  1605. #else
  1606. X    union wait status;
  1607. #endif /* SYSV */
  1608. #ifdef SIGCONT
  1609. X    SIGRET (*oldstop)(), (*oldcont)();
  1610. #endif /* SIGCONT */
  1611. X    int pid;
  1612. X    SIGRET (*oldint)(), (*oldquit)();
  1613. X
  1614. X    oldint = signal(SIGINT, SIG_IGN);
  1615. X    oldquit = signal(SIGQUIT, SIG_IGN);
  1616. #ifdef SIGCONT
  1617. X    oldstop = signal(SIGTSTP, SIG_DFL);
  1618. X    oldcont = signal(SIGCONT, SIG_DFL);
  1619. #endif /* SIGCONT */
  1620. X    turnon(glob_flags, IGN_SIGS);
  1621. X
  1622. X    echo_on();
  1623. X    if (!setjmp(execjbuf)) {
  1624. X    if ((exec_pid = vfork()) == 0) {
  1625. X        (void) signal(SIGINT, SIG_DFL);
  1626. X        (void) signal(SIGQUIT, SIG_DFL);
  1627. X        (void) signal(SIGPIPE, SIG_DFL);
  1628. X        (void) closefileds(3);    /* close all descriptors above 2 */
  1629. X        execvp(*argv, argv);
  1630. X        if (errno == ENOENT)
  1631. X        print("%s: command not found.\n", *argv);
  1632. X        else
  1633. X        error(*argv);
  1634. X        _exit(-1);
  1635. X    }
  1636. X    /* Parent's got to do something; sigchldcatcher may also be waiting.
  1637. X     * This loop will usually get broken by the longjmp() (except tool),
  1638. X     * but in certain circumstances sigchldcatcher isn't yet active.
  1639. X     */
  1640. X    while ((pid = wait(&status)) != -1 && pid != exec_pid)
  1641. X        Debug("The exec loop caught a signal? (pid = %d)\n", pid);
  1642. X    }
  1643. X    /* reset our ttymodes */
  1644. X    echo_off();
  1645. X    (void) signal(SIGINT, oldint);
  1646. X    (void) signal(SIGQUIT, oldquit);
  1647. #ifdef SIGCONT
  1648. X    (void) signal(SIGTSTP, oldstop);
  1649. X    (void) signal(SIGCONT, oldcont);
  1650. #endif /* SIGCONT */
  1651. X    turnoff(glob_flags, IGN_SIGS);
  1652. }
  1653. X
  1654. SIGRET
  1655. sigchldcatcher()
  1656. {
  1657. #ifdef SYSV
  1658. X    int status;
  1659. #else
  1660. X    union wait status;
  1661. #endif /* SYSV */
  1662. X    int       pid;
  1663. X
  1664. #ifdef BSD
  1665. X    while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
  1666. X    Debug("%d died...\n", pid);
  1667. X    if (pid == exec_pid)
  1668. X        break;
  1669. X    }
  1670. #else
  1671. #ifndef SYSV
  1672. X    while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid)
  1673. X    Debug("%d died...\n", pid);
  1674. #else /* SYSV */
  1675. X    while ((pid = wait((int *)0)) > 0 && pid != exec_pid)
  1676. X    Debug("%d died...\n", pid);
  1677. #endif /* SYSV */
  1678. #endif /* BSD */
  1679. X    if (pid == exec_pid && pid > 0) {
  1680. X    exec_pid = 0;
  1681. X    longjmp(execjbuf, 1);
  1682. X    }
  1683. }
  1684. SHAR_EOF
  1685. chmod 0644 execute.c ||
  1686. echo 'restore of execute.c failed'
  1687. Wc_c="`wc -c < 'execute.c'`"
  1688. test 4196 -eq "$Wc_c" ||
  1689.     echo 'execute.c: original size 4196, current size' "$Wc_c"
  1690. rm -f _shar_wnt_.tmp
  1691. fi
  1692. # ============= expr.c ==============
  1693. if test -f 'expr.c' -a X"$1" != X"-c"; then
  1694.     echo 'x - skipping expr.c (File already exists)'
  1695.     rm -f _shar_wnt_.tmp
  1696. else
  1697. > _shar_wnt_.tmp
  1698. echo 'x - extracting expr.c (Text)'
  1699. sed 's/^X//' << 'SHAR_EOF' > 'expr.c' &&
  1700. /* @(#)expr.c    2.3    (c) copyright 10/15/86 (Dan Heller) */
  1701. X
  1702. #include "mush.h"
  1703. X
  1704. char *eval_expr();
  1705. X
  1706. /* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
  1707. X * delimited by whitespace or comma's. Set msg_list bitfields using
  1708. X * macros in mush.h.
  1709. X * Return the address of the end of whatever we parsed (in case there's
  1710. X * more that the calling routine cares to deal with).
  1711. X * Finally, remember that user specifies one more than actual message number
  1712. X */
  1713. char *
  1714. do_range(p, list1)
  1715. register char *p, *list1;
  1716. {
  1717. X    register int num1 = -1, num2 = -1, except = 0;
  1718. X    register char *p2;
  1719. X    char list2[MAXMSGS_BITS];
  1720. X
  1721. X    if (!p)
  1722. X    return "";
  1723. X    while (*p) {
  1724. X    if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
  1725. X        if (isdigit(*p)) {
  1726. X        char c;
  1727. X        p2 = p;
  1728. X        skipdigits(0);  /* find the end of the digits */
  1729. X        c = *p, *p = 0; /* temporarily plug a null */
  1730. X        if (!(num2 = chk_msg(p2))) {
  1731. X            clear_msg_list(list1);
  1732. X            return NULL;
  1733. X        }
  1734. X        *p = c;
  1735. X        } else if (*p == '$')
  1736. X        p++, num2 = msg_cnt;
  1737. X        else if (*p == '.')
  1738. X        p++, num2 = current_msg+1;
  1739. X        else if (*p == '^')
  1740. X        p++, num2 = 1;
  1741. X        if (except)
  1742. X        unset_msg_bit(list1, num2-1);
  1743. X        else
  1744. X        set_msg_bit(list1, num2-1);
  1745. X        if (num1 >= 0) {
  1746. X        if (num1 > num2) {
  1747. X            print("syntax error: range sequence order reversed.\n");
  1748. X            clear_msg_list(list1);
  1749. X            return NULL;
  1750. X        }
  1751. X        while (++num1 < num2)
  1752. X            if (except)
  1753. X            unset_msg_bit(list1, num1-1);
  1754. X            else
  1755. X            set_msg_bit(list1, num1-1);
  1756. X        num1 = num2 = -1;
  1757. X        }
  1758. X    }
  1759. X    /* expressions to evaluate start with a `
  1760. X     * p2 points to first char passed the last char parsed.
  1761. X     */
  1762. X    if (*p == '`') {
  1763. X        clear_msg_list(list2);
  1764. X        if (!(p = eval_expr(p, list2))) {
  1765. X        clear_msg_list(list1);
  1766. X        return NULL;
  1767. X        } else {
  1768. X        if (except)
  1769. X            bitput(list2, list1, msg_cnt, &=~); /* MACRO */
  1770. X        else
  1771. X            bitput(list2, list1, msg_cnt, |=); /* MACRO */
  1772. X        }
  1773. X    }
  1774. X    /* NOT operator: `* {5}' (everything except for 5)
  1775. X     * `4-16 {8-10}'  (4 thru 16 except for 8,9,10)
  1776. X     */
  1777. X    if (*p == '{' || *p == '}') {
  1778. X        if (*p == '{' && (except || num1 >= 0))
  1779. X        break;
  1780. X        if (*p == '}' && !except) {
  1781. X        print("syntax error: missing {\n"); /* } */
  1782. X        break;
  1783. X        }
  1784. X        except = !except;
  1785. X    } else if (*p == '-')
  1786. X        if (num1 >= 0 || num2 < 0
  1787. X            || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
  1788. X        break;
  1789. X        else
  1790. X        num1 = num2;
  1791. X    else if (*p == ',' || *p == '*') {
  1792. X        if (num1 >= 0)
  1793. X        break;
  1794. X        else if (*p == '*') {
  1795. X        if (except)
  1796. X            clear_msg_list(list1);
  1797. X        else
  1798. X            for (num1 = 0; num1 < msg_cnt; num1++)
  1799. X            set_msg_bit(list1, num1);
  1800. X        num1 = -1;
  1801. X        }
  1802. X    } else if (!index(" \t`", *p))
  1803. X        break;
  1804. X    if (*p)
  1805. X        skipspaces(1); /* don't make user type stuff squished together */
  1806. X    }
  1807. X    if (num1 >= 0 || except) {
  1808. X    if (except)
  1809. X        /* { */ print("syntax error: unmatched }\n");
  1810. X    else
  1811. X        print("syntax error: unfinished range\n");
  1812. X    clear_msg_list(list1);
  1813. X    return NULL;
  1814. X    }
  1815. X    return p;
  1816. }
  1817. X
  1818. /*
  1819. X * convert a message list to an ascii string.
  1820. X */
  1821. void
  1822. list_to_str(list, str)
  1823. char list[], *str;
  1824. {
  1825. X    int n, m = -1;
  1826. X
  1827. X    for (n = 0; n < msg_cnt; n++) {
  1828. X    if (msg_bit(list, n)) {
  1829. X        if (m == -1)
  1830. X        str += strlen(sprintf(str, "%d", (m = n) + 1 ));
  1831. X        continue;
  1832. X    }
  1833. X    if (m == -1)
  1834. X        continue;
  1835. X    if (n - m > 2)
  1836. X        str += strlen(sprintf(str, "-%d", n));
  1837. X    else if (n - m == 2)
  1838. X        str += strlen(sprintf(str, " %d", n));
  1839. X    *str++ = ' ';
  1840. X    m = -1;
  1841. X    }
  1842. X    if (m > -1 && m != n - 1) {
  1843. X    if (n - m > 2)
  1844. X        *str++ = '-';
  1845. X    else
  1846. X        *str++ = ' ';
  1847. X    str += Strcpy(str, itoa(msg_cnt));
  1848. X    }
  1849. X    *str = 0;
  1850. }
  1851. X
  1852. /* evaluate expressions:
  1853. X * mail> delete `pick -f root`     deletes all messages from root.
  1854. X * mail> save * {`pick -s "Re:"`}  save all message that don't have "Re:"
  1855. X *                   in the subject header.
  1856. X * mail> save `pick -x -s "Re:"`   same
  1857. X * args as follows:
  1858. X *   p should point to the first ` -- check for it.
  1859. X *   on tells whether to turn bits on or off if messages match.
  1860. SHAR_EOF
  1861. true || echo 'restore of expr.c failed'
  1862. fi
  1863. echo 'End of  part 7'
  1864. echo 'File expr.c is continued in part 8'
  1865. echo 8 > _shar_seq_.tmp
  1866. exit 0
  1867. exit 0 # Just in case...
  1868. -- 
  1869. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1870. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1871. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1872. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1873.