home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1602 < prev    next >
Encoding:
Text File  |  1990-12-28  |  33.1 KB  |  1,204 lines

  1. Newsgroups: alt.sources
  2. From: goer@sophist.uucp (Richard Goerwitz)
  3. Subject: Jewish/Civil calendar, part 01 of 03
  4. Message-ID: <1990Jul20.000900.4359@midway.uchicago.edu>
  5. Date: Fri, 20 Jul 90 00:09:00 GMT
  6.  
  7.  
  8. This is an experimental posting of a Unix port of an MS-DOS program
  9. written in Icon.  Icon, for those who do not know, is the successor
  10. language to Snobol (in fact SL5).  It retains great string handling
  11. facilities of Snobol, and yet possesses a fully procedural structure.
  12. It also incorporates data structures such as hash tables and linked
  13. lists, and provides builtin garbage collection, like most dialects
  14. of Lisp.  I personally use it for natural language processing, but
  15. it can also be used for rapid prototying of almost anything except
  16. low-level bit manipulation and systems programming jobs.  It is popu-
  17. lar among people doing all varieties of nonnumeric computing.
  18.  
  19. The program itself - yes, by Jove, there is a program here - is a
  20. Jewish/Civil calendar display utility.  Lets you view corresponding
  21. dates for both calendars on screen simultaneously.  I've never un-
  22. derstood the Jewish calendar, and this seemed a good excuse to learn
  23. all the month names.  My real reason for porting it was that it was
  24. the first piece of software posted to comp.lang.icon that seemed a
  25. good way of testing my rough port of the C/Unix termlib library to
  26. Icon.  I thank Alan Corre (the original author) for permitting me to
  27. (ab)use the original MS-DOS program in this way.
  28.  
  29. Anyone who does not have Icon is without excuse, since it is free,
  30. and available for many, many popular micros, minis, and some main-
  31. frames.  Just about anything that calls itself -nix can run Icon
  32. (Unix, Xenix, etc.).  Ftp it from cs.arizona.edu if you find your
  33. curiosity aroused, and don't already have it installed.
  34.  
  35.    -Richard L. Goerwitz              goer%sophist@uchicago.bitnet
  36.    goer@sophist.uchicago.edu         rutgers!oddjob!gide!sophist!goer
  37.  
  38.  
  39. ---- Cut Here and unpack ----
  40. #!/bin/sh
  41. # This is a shell archive (shar 3.24)
  42. # made 07/19/1990 22:27 UTC by goer@sophist.uchicago.edu
  43. # Source directory /u/richard/Hebcalen
  44. #
  45. # existing files WILL be overwritten
  46. # This format requires very little intelligence at unshar time.
  47. # "echo" and "sed" will be needed.
  48. #
  49. # This is part 1 of a multipart archive                                    
  50. # do not concatenate these parts, unpack them in order with /bin/sh        
  51. #
  52. # This shar contains:
  53. # length  mode       name
  54. # ------ ---------- ------------------------------------------
  55. #  23020 -r--r--r-- hebcalen.src
  56. #  11276 -r--r--r-- itlib.icn
  57. #   4008 -rw-r--r-- hebcalen.hlp
  58. #   6490 -rw-r--r-- hebcalen.dat
  59. #   2475 -rw-r--r-- README
  60. #   1654 -rw-r--r-- Makefile.dist
  61. #  29360 -rw-r--r-- cal.text
  62. #
  63. if test -r shar3_seq_.tmp; then
  64.     echo "Must unpack archives in sequence!"
  65.     next=`cat shar3_seq_.tmp`; echo "Please unpack part $next next"
  66.     exit 1
  67. fi
  68. # ============= hebcalen.src ==============
  69. echo "x - extracting hebcalen.src (Text)"
  70. sed 's/^X//' << 'SHAR_EOF' > hebcalen.src &&
  71. X##########################################################################
  72. X#
  73. X#    NAME:   hebcalen.icn
  74. X#
  75. X#    TITLE:  Combination Jewish/Civil calendar
  76. X#
  77. X#    AUTHOR: Alan D. Corre (ported to Unix by Richard Goerwitz)   
  78. X#
  79. X#    DATE:   7/19/90 (version 1.11)
  80. X#
  81. X##########################################################################
  82. X#
  83. X#  COPYRIGHT (c) 1990, Alan D. Corre
  84. X#
  85. X#  Permission is hereby given to all persons to copy, compile and pass
  86. X#  to others this code provided that (1) it is not used for monetary
  87. X#  gain; (2) it is not subverted from its original purpose, and is
  88. X#  changed only to the extent necessary to make it work on a different
  89. X#  computer or terminal.  No guarantees are given or implied as to the
  90. X#  correctness of information furnished by this program.
  91. X#
  92. X##########################################################################
  93. X#
  94. X#  This work is respectfully devoted to the authors of two books
  95. X#  consulted with much profit: "A Guide to the Solar-Lunar Calendar"
  96. X#  by B. Elihu Rothblatt published by our sister Hebrew Dept. in
  97. X#  Madison, Wis., and "Kiddush HaHodesh" by Rabbenu Moses ben Maimon,
  98. X#  on whom be peace.
  99. X#
  100. X#  The Jewish year harmonizes the solar and lunar cycle, using the
  101. X#  19-year cycle of Meton (c. 432 BCE). It corrects so that certain
  102. X#  dates shall not fall on certain days for religious convenience. The
  103. X#  Jewish year has six possible lengths, 353, 354, 355, 383, 384, and
  104. X#  385 days, according to day and time of new year lunation and
  105. X#  position in Metonic cycle.  Time figures from 6pm previous night.
  106. X#  The lunation of year 1 is calculated to be on a Monday (our Sunday
  107. X#  night) at ll:11:20pm. Our data table begins with a hypothetical
  108. X#  year 0, corresponding to 3762 B.C.E.  Calculations in this program
  109. X#  are figured in the ancient Babylonian unit of halaqim "parts" of
  110. X#  the hour = 1/1080 hour.
  111. X#
  112. X#  Startup syntax is simply hebcalen [date], where date is a year
  113. X#  specification of the form 5750 for a Jewish year, +1990 or 1990AD
  114. X#  or 1990CE or -1990 or 1990BC or 1990BCE for a civil year.
  115. X#
  116. X#  (Bugs:  Years over 6039 are calculated from scratch (slow).  I've
  117. X#  also noticed that the dates are incorrect (e.g. hebcalen +7777
  118. X#  will display civil year 7757).  I have not delved into the pro-
  119. X#  gram deep enough to pinpoint the cause of the dating discrepancy.
  120. X#  - RLG)
  121. X#
  122. X##########################################################################
  123. X
  124. X
  125. Xrecord date(yr,mth,day)
  126. Xrecord molad(day,halaqim)
  127. Xglobal cyr,jyr,days_in_jyr,current_molad,current_day,infolist
  128. X
  129. X
  130. X#------- the following sections of code have been modified  - RLG -------#
  131. X
  132. Xprocedure main(a)
  133. X
  134. X    iputs(getval("ti"))
  135. X    display_startup_screen()
  136. X
  137. X    if *a = 0 then {
  138. X    #put()'ing an asterisk means that user might need help
  139. X    n := 1; put(a,"*")
  140. X    }
  141. X    else n := *a
  142. X    every p := 1 to n do {
  143. X    initialize(a[p]) | break
  144. X    process() | break
  145. X    }
  146. X    iputs(getval("te"))
  147. X
  148. Xend
  149. X
  150. X
  151. X
  152. Xprocedure display_startup_screen()
  153. X
  154. X    local T
  155. X
  156. X    clear()
  157. X    banner("PERPETUAL JEWISH/CIVIL CALENDAR","by","ALAN D. CORRE")
  158. X    # Use a combination of tricks to be sure it will be up there a sec.
  159. X    every 1 to 10000
  160. X    T := &time; until &time > (T+450)
  161. X
  162. X    return
  163. X
  164. Xend
  165. X
  166. X
  167. X
  168. Xprocedure banner(l[])
  169. X
  170. X    # Creates a banner to begin hebcalen.  Leaves it on the screen for
  171. X    # about a second.
  172. X
  173. X    local m, n, CM, COLS, LINES
  174. X
  175. X    CM    := getval("cm")
  176. X    COLS  := getval("co")
  177. X    LINES := getval("li")
  178. X    (COLS > 55, LINES > 9) |
  179. X    stop("\nSorry, your terminal just isn't big enough.")
  180. X
  181. X    if LINES > 20 then {
  182. X    # Terminal is big enough for banner.
  183. X    iputs(igoto(CM,1,3))
  184. X    writes("+",repl("-",COLS-3),"+")
  185. X    iputs(igoto(CM,1,4))
  186. X    writes("|")
  187. X    iputs(igoto(CM,COLS-1,4))
  188. X    writes("|")
  189. X
  190. X    m := 0
  191. X    every n := 5 to (*l * 3) + 4 by 3 do {
  192. X        iputs(igoto(CM,1,n))
  193. X        writes("|",center(l[m+:=1],COLS-3),"|")
  194. X        every iputs(igoto(CM,1,n+(1|2))) & writes("|")
  195. X        every iputs(igoto(CM,COLS-1,n+(1|2))) & writes("|")
  196. X    }
  197. X    
  198. X    iputs(igoto(CM,1,n+3))
  199. X    writes("+",repl("-",COLS-3),"+")
  200. X    iputs(igoto(CM,1,n+4))
  201. X    write(" Copyright (c) Alan D. Corre, 1990")
  202. X    }
  203. X    else {
  204. X    # Terminal is extremely short
  205. X    iputs(igoto(CM,1,(LINES/2)-1))
  206. X    write(center(l[1],COLS))
  207. X    write(center("Copyright (c) Alan D. Corre, 1990",COLS))
  208. X    }    
  209. X
  210. X    return
  211. X
  212. Xend
  213. X
  214. X
  215. X
  216. Xprocedure get_paths()
  217. X
  218. X    local paths, p
  219. X
  220. X    suspend "./" | "/usr/local/lib/hebcalen/"
  221. X    paths := getenv("PATH")
  222. X    \paths ? {
  223. X    tab(match(":"))
  224. X    while p := 1(tab(find(":")), move(1))
  225. X    do suspend "" ~== trim(p,'/ ') || "/"
  226. X    return "" ~== trim(tab(0) \ 1,'/ ') || "/"
  227. X    }
  228. X
  229. Xend
  230. X
  231. X
  232. X
  233. Xprocedure instructions(filename)
  234. X
  235. X    # Gives user access to a help file which is printed out in chunks
  236. X    # by "more."
  237. X
  238. X    local helpfile, pager, ans
  239. X
  240. X    iputs(igoto(getval("cm"),1,2))
  241. X    writes("Do you need instructions? [ny]  ")
  242. X    ans := map(read())
  243. X    "q" == ans & fail
  244. X
  245. X    if "y" == ans then {
  246. X    if close(open(helpfile := (get_paths()||filename)))
  247. X    then {
  248. X        # Kludge, kludge, kludge.
  249. X        close(open(
  250. X        more_file := (
  251. X            ("" ~== getenv("PAGER")) |
  252. X            (("/bin/"|"/usr/ucb/"|"/usr/bin/")||"more"))))
  253. X        system(more_file || " " || helpfile)
  254. X    }
  255. X    else write("Can't find your hebcalen.hlp file!")
  256. X    iputs(igoto(getval("cm"),1,getval("li")))
  257. X    boldface()
  258. X    writes("Press return to continue.")
  259. X    normal()
  260. X    "q" == map(read()) & fail
  261. X    }
  262. X
  263. X    return \helpfile | "no help"
  264. X
  265. Xend
  266. X
  267. X
  268. X
  269. Xprocedure clear()
  270. X
  271. X    # Clears the screen.  Tries several methods.
  272. X
  273. X    if not iputs(getval("cl"))
  274. X    then iputs(igoto(getval("cm"),1,1))
  275. X    if not iputs(getval("cd"))
  276. X    then {
  277. X    every i := 1 to getval("li") do {
  278. X        iputs(igoto(getval("cm"),1,i))
  279. X        iputs(getval("ce"))
  280. X    }
  281. X    iputs(igoto(getval("cm"),1,1))
  282. X    }
  283. X
  284. Xend
  285. X
  286. X
  287. X
  288. Xprocedure initialize_list()
  289. X
  290. X    # Put info of hebcalen.dat into a global list
  291. X
  292. X    local infile,n
  293. X
  294. X    infolist := list(301)
  295. X    if not (infile := open(get_paths()||"hebcalen.dat")) then
  296. X    stop("\nError:  hebcalen.dat must be in your path or the current dir.")
  297. X
  298. X    # The table is arranged at twenty year intervals with 301 entries.
  299. X    every n := 1 to 301 do
  300. X    infolist[n] := read(infile)
  301. X    close(infile)
  302. X
  303. Xend
  304. X
  305. X
  306. X
  307. Xprocedure initialize_variables()
  308. X
  309. X    # Get the closest previous year in the table.
  310. X
  311. X    local line, quotient
  312. X
  313. X    quotient := jyr.yr / 20 + 1
  314. X    # Only 301 entries. Figure from last if necessary.
  315. X    if quotient > 301 then quotient := 301
  316. X    # Pull the appropriate info, put into global variables.
  317. X    line := infolist[quotient]
  318. X
  319. X    line ? {
  320. X    current_molad.day := tab(upto('%'))
  321. X    move(1)
  322. X    current_molad.halaqim := tab(upto('%'))
  323. X    move(1)
  324. X    cyr.mth := tab(upto('%'))
  325. X    move(1)
  326. X    cyr.day := tab(upto('%'))
  327. X    move(1)
  328. X    cyr.yr := tab(upto('%'))
  329. X    days_in_jyr := line[-3:0]
  330. X    }
  331. X
  332. X    # Begin at rosh hashana.
  333. X    jyr.day := 1
  334. X    jyr.mth := 7
  335. X    return
  336. X
  337. Xend
  338. X
  339. X
  340. X
  341. Xprocedure initialize(yr)
  342. X
  343. X    local year
  344. X    static current_year
  345. X
  346. X    # initialize global variables
  347. X    initial {
  348. X    cyr := date(0,0,0)
  349. X    jyr := date(0,0,0)
  350. X    current_molad := molad(0,0)
  351. X    initialize_list()
  352. X    current_year := get_current_year()
  353. X    }
  354. X
  355. X    clear()
  356. X    #user may need help
  357. X    if yr == "*" then {
  358. X    instructions("hebcalen.hlp") | fail
  359. X    clear()
  360. X    iputs(igoto(getval("cm"),1,2))
  361. X    write("Enter a year.  By default, all dates are interpreted")
  362. X    write("according to the Jewish calendar.  Civil years should")
  363. X    write("be preceded by a + or - sign to indicate occurrence")
  364. X    write("relative to the beginning of the common era (the cur-")
  365. X    writes("rent civil year, ",current_year,", is the default):  ")
  366. X    boldface()
  367. X    year := read()
  368. X    normal()
  369. X    "q" == map(year) & fail
  370. X    }
  371. X    else year := yr
  372. X
  373. X    "" == year & year := current_year
  374. X    until jyr.yr := cleanup(year) do {
  375. X    writes("\nI don't consider ")
  376. X    boldface()
  377. X    writes(year)
  378. X    normal()
  379. X    writes(" a valid date.  Try again:  ")
  380. X    boldface()
  381. X    year := read()
  382. X    normal()
  383. X    "q" == map(year) & fail
  384. X    "" == year & year := current_year
  385. X    }
  386. X
  387. X    clear()
  388. X    initialize_variables()
  389. X    return
  390. X
  391. Xend
  392. X
  393. X
  394. X
  395. Xprocedure get_current_year()
  396. X    &date ? c_date := tab(find("/"))
  397. X    return "+" || c_date
  398. Xend
  399. X
  400. X
  401. X
  402. Xprocedure cleanup(str)
  403. X
  404. X    # Tidy up the string. Bugs still possible.
  405. X
  406. X    if "" == trim(str) then return ""
  407. X
  408. X    map(Strip(str,~(&digits++'ABCDE+-'))) ? {
  409. X
  410. X    if find("-"|"bc"|"bcd")
  411. X    then return (0 < (3761 - (0 ~= checkstr(str))))
  412. X    else if find("+"|"ad"|"ce")
  413. X    then return ((0 ~= checkstr(str)) + 3760)
  414. X    else if 0 < integer(str)
  415. X    then return str
  416. X    else fail
  417. X    
  418. X    }
  419. X
  420. Xend
  421. X
  422. X
  423. X
  424. Xprocedure Strip(s,c)
  425. X
  426. X    s2 := ""
  427. X    s ? {
  428. X    while s2 ||:= tab(upto(c))
  429. X    do tab(many(c))
  430. X    s2 ||:= tab(0)
  431. X    }
  432. X    return s2
  433. X
  434. Xend
  435. X
  436. X
  437. X
  438. Xprocedure checkstr(s)
  439. X
  440. X    # Does preliminary work on string before cleanup() cleans it up.
  441. X
  442. X    local letter,n,newstr
  443. X
  444. X    newstr := ""
  445. X    every newstr ||:= string(integer(!s))
  446. X    if 0 = *newstr | "" == newstr
  447. X    then fail
  448. X    else return newstr
  449. X
  450. Xend
  451. X
  452. X
  453. X
  454. Xprocedure process()
  455. X
  456. X    # Extracts information about the specified year.
  457. X
  458. X    local msg, limit, dj, dc, month_count, done
  459. X    static how_many_per_screen, how_many_screens
  460. X    initial {
  461. X    how_many_per_screen := how_many_can_fit()
  462. X    (how_many_screens := seq()) * how_many_per_screen >= 12
  463. X    }
  464. X
  465. X    # 6039 is last year handled by the table in the usual way.
  466. X    if jyr.yr > 6039
  467. X    then msg := "Calculating.  Years over 6039 take a long time."
  468. X    else msg := "Calculating."
  469. X    if jyr.yr <= 6039 then {
  470. X    limit := jyr.yr % 20 
  471. X    jyr.yr := ((jyr.yr / 20) * 20)} else {
  472. X            # Otherwise figure from 6020 and good luck
  473. X        limit := jyr.yr - 6020
  474. X        jyr.yr := 6020
  475. X    }
  476. X
  477. X    ans := "y"
  478. X    establish_jyr()
  479. X    iputs(igoto(getval("cm"),1,2))
  480. X    writes(msg)
  481. X    every 1 to limit do {
  482. X    # Increment the years, establish the type of Jewish year
  483. X    cyr_augment()
  484. X    jyr_augment()
  485. X    establish_jyr()
  486. X    }
  487. X
  488. X    clear() 
  489. X    while ("y"|"") == map(ans) do {
  490. X
  491. X    yj := jyr.yr
  492. X    dj := days_in_jyr
  493. X
  494. X    month_count := 0
  495. X    # On the variable how_many_screens, see initial { } above
  496. X    every n := 1 to how_many_screens do {
  497. X        clear()
  498. X        every 1 to how_many_per_screen do {
  499. X        write_a_month()
  500. X        (month_count +:= 1) = 12 & break
  501. X        }
  502. X        if month_count < 12 | (12 % (13 > how_many_per_screen)) = 0
  503. X        then {
  504. X
  505. X        iputs(igoto(getval("cm"),1,getval("li")-2))
  506. X        boldface()
  507. X        writes(status_line(yj,dj))
  508. X        normal()
  509. X
  510. X        if month_count < 12 | jyr.mth = 6 then {
  511. X            iputs(igoto(getval("cm"),1,getval("li")-1))
  512. X            writes("Press return to continue.  ")
  513. X            "q" == map(read()) & fail
  514. X        }
  515. X        }
  516. X    }
  517. X
  518. X    if jyr.mth = 6 then {
  519. X        if (12 % (13 > how_many_per_screen)) = 0
  520. X        then clear()
  521. X        write_a_month()
  522. X    }
  523. X    iputs(igoto(getval("cm"),1,getval("li")-2))
  524. X    boldface()
  525. X    writes(status_line(yj,dj))
  526. X    normal()
  527. X
  528. X    iputs(igoto(getval("cm"),1,getval("li")-1))
  529. X    writes("Display the next year? [yn]  ")
  530. X    ans := read()
  531. X
  532. X    }
  533. X    return
  534. X
  535. Xend
  536. X
  537. X
  538. X
  539. Xprocedure how_many_can_fit()
  540. X
  541. X    local LINES, how_many
  542. X
  543. X    LINES := getval("li") + 1
  544. X    (((8 * (how_many := 1 to 14)) / LINES) = 1)
  545. X
  546. X    return how_many - 1
  547. X
  548. Xend
  549. X
  550. X
  551. X
  552. Xprocedure cyr_augment()
  553. X
  554. X    # Make civil year a year later, we only need consider Aug,Sep,Nov.
  555. X
  556. X    local days,newmonth,newday
  557. X
  558. X    if cyr.mth = 8 then
  559. X    days := 0 else
  560. X    if cyr.mth = 9 then
  561. X    days := 31 else
  562. X    if cyr.mth = 10 then
  563. X    days := 61 else
  564. X    stop("Error in cyr_augment")
  565. X
  566. X    writes(".")
  567. X
  568. X    days := (days + cyr.day-365+days_in_jyr)
  569. X    if isleap(cyr.yr + 1) then days -:= 1
  570. X
  571. X    # Cos it takes longer to get there.
  572. X    if days <= 31 then {newmonth := 8; newday := days} else
  573. X    if days <= 61 then {newmonth := 9; newday := days-31} else
  574. X    {newmonth := 10; newday := days-61} 
  575. X
  576. X    cyr.mth := newmonth
  577. X    cyr.day := newday
  578. X    cyr.yr +:= 1
  579. X    if cyr.yr = 0 then cyr.yr := 1
  580. X
  581. X    return
  582. X
  583. Xend
  584. X
  585. X
  586. X
  587. Xprocedure header()
  588. X
  589. X    # Creates the header for Jewish and English side.  Bug:  This
  590. X    # routine, as it stands, has to rewrite the entire screen, in-
  591. X    # cluding blank spaces.  Many of these could be elminated by
  592. X    # judicious line clears and/or cursor movement commands.  Do-
  593. X    # ing so would certainly speed up screen refresh for lower
  594. X    # baud rates.  I've utilized the ch command where available,
  595. X    # but in most cases, plain old spaces must be output.
  596. X
  597. X    static make_whitespace, whitespace
  598. X    initial {
  599. X    COLS := getval("co")
  600. X    if getval("ch") then {
  601. X        # Untested, but it would offer a BIG speed advantage!
  602. X        make_whitespace := create |iputs(igoto(getval("ch"),(COLS-53)+25))
  603. X    }
  604. X    else {
  605. X        # Have to do things this way, since we don't know what line
  606. X        # we are on (cm commands usually default to row/col 1).
  607. X        whitespace := repl(" ",COLS-53)
  608. X        make_whitespace := create |writes(whitespace)
  609. X    }
  610. X    }
  611. X
  612. X    writes(repl(" ",7),"S",repl(" ",2),"M",repl(" ",2),"T",repl(" ",2),"W",
  613. X       repl(" ",2),"T",repl(" ",2),"F",repl(" ",2))
  614. X    boldface()
  615. X    writes("S")
  616. X    normal()
  617. X    @make_whitespace
  618. X    writes("S",repl(" ",2),"M",repl(" ",2),"T",repl(" ",2),"W",
  619. X        repl(" ",2),"T",repl(" ",2),"F",repl(" ",2))
  620. X    boldface()
  621. X    writes("S")
  622. X    normal()
  623. X    iputs(getval("ce"))
  624. X    write()
  625. X
  626. Xend
  627. X
  628. X
  629. X
  630. Xprocedure write_a_month()
  631. X
  632. X    # Writes a month on the screen
  633. X
  634. X    header()
  635. X    every 1 to 5 do {
  636. X    writes(make_a_line())
  637. X    iputs(getval("ce"))
  638. X    write()
  639. X    }
  640. X    if jyr.day ~= 1 then {
  641. X    writes(make_a_line())
  642. X    iputs(getval("ce"))
  643. X    write()
  644. X    }
  645. X    iputs(getval("ce"))
  646. X    write()
  647. X
  648. X    return
  649. X
  650. Xend
  651. X
  652. X
  653. X
  654. Xprocedure status_line(a,b)
  655. X
  656. X    # Create the status line at the bottom of screen.
  657. X
  658. X    local sline,c,d
  659. X
  660. X    c := cyr.yr
  661. X    if (cyr.day = 1) & (cyr.mth = 1) then c -:= 1
  662. X    d := { if isleap(c) then 366 else 365 }
  663. X    if getval("co") > 79 then {
  664. X    sline := ("Year of Creation: " || a || "  Days in year: " || b ||
  665. X          "  Civil year: " || c || "  Days in year: " || d)
  666. X    }
  667. X    else {
  668. X    sline := ("Jewish year " || a || " (" || b || " days)," ||
  669. X          " Civil year " || c || " (" || d || " days)")
  670. X    }
  671. X
  672. X    return center(sline,getval("co"))
  673. X
  674. Xend
  675. X
  676. X
  677. X
  678. Xprocedure boldface()
  679. X    
  680. X    static bold_str, cookie_str
  681. X    initial {
  682. X    if bold_str := getval("so")
  683. X    then cookie_str := repl(getval("bc") | "\b", getval("sg"))
  684. X    else {
  685. X        if bold_str := getval("ul")
  686. X        then cookie_str := repl(getval("bc") | "\b", getval("ug"))
  687. X    }
  688. X    }        
  689. X    
  690. X    iputs(\bold_str)
  691. X    iputs(\cookie_str)
  692. X    return
  693. X
  694. Xend
  695. X
  696. X
  697. X
  698. Xprocedure normal()
  699. X
  700. X    static UN_bold_str, cookie_str
  701. X    initial {
  702. X    if UN_bold_str := getval("se")
  703. X    then cookie_str := repl(getval("bc") | "\b", getval("sg"))
  704. X    else {
  705. X        if UN_bold_str := getval("ue")
  706. X        then cookie_str := repl(getval("bc") | "\b", getval("ug"))
  707. X    }
  708. X    }        
  709. X    
  710. X    iputs(\UN_bold_str)
  711. X    iputs(\cookie_str)
  712. X    return
  713. X
  714. Xend
  715. X
  716. X
  717. X#--------------------- end modified sections of code ----------------------#
  718. X
  719. X# Okay, okay a couple of things have been modified below, but nothing major.
  720. X
  721. Xprocedure make_a_line()
  722. X#make a single line of the months
  723. Xlocal line,blanks1,blanks2,start_point,end_point,flag,fm
  724. Xstatic number_of_spaces
  725. Xinitial number_of_spaces := getval("co")-55
  726. X
  727. X#consider the first line of the month
  728. X  if jyr.day = 1 then {
  729. X    line := mth_table(jyr.mth,1)
  730. X#setting flag means insert civil month at end of line    
  731. X    flag := 1 } else
  732. X    line := repl(" ",3)
  733. X#consider the case where first day of civil month is on Sunday    
  734. X  if (cyr.day = 1) & (current_day = 1) then flag := 1
  735. X#space between month name and beginning of calendar
  736. X  line ||:= repl(" ",2)
  737. X#measure indentation for first line
  738. X  line ||:= blanks1 := repl(" ",3*(current_day-1))
  739. X#establish start point for Hebrew loop
  740. X  start_point := current_day
  741. X#establish end point for Hebrew loop and run civil loop
  742. X  every end_point := start_point to 7 do {
  743. X    line ||:= right(jyr.day,3)
  744. X    if not j_augment() then {jyr_augment(); establish_jyr(); current_day -:= 1; if current_day = 0 then current_day := 7}
  745. X    d_augment()
  746. X    if jyr.day = 1 then break }
  747. X#measure indentation for last line
  748. X  blanks2 := repl(" ",3*(7-end_point))
  749. X  line ||:= blanks2; line ||:= repl(" ",number_of_spaces); line ||:= blanks1
  750. X  every start_point to end_point do {
  751. X    line ||:= right(cyr.day,3)
  752. X    if (cyr.day = 1) then flag := 1 
  753. X    augment()}
  754. X  line ||:= blanks2 ||:= repl(" ",3)
  755. X  fm := cyr.mth
  756. X  if cyr.day = 1 then
  757. X    if cyr.mth = 1 then fm := 12 else fm := cyr.mth - 1
  758. X  if \flag then line ||:= mth_table(fm,2) else
  759. X    line ||:= repl(" ",3)
  760. Xreturn line
  761. Xend
  762. X
  763. Xprocedure mth_table(n,p)
  764. X#generates the short names of Jewish and Civil months. Get to civil side
  765. X#by adding 13 (=max no of Jewish months)
  766. Xstatic corresp
  767. Xinitial corresp := ["NIS","IYA","SIV","TAM","AV ","ELU","TIS","HES","KIS",
  768. X"TEV","SHE","ADA","AD2","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP",
  769. X"OCT","NOV","DEC"]
  770. X  if (p ~= 1) & (p ~= 2) then stop("ERROR IN MTH-TABLE") else
  771. X    if p = 2 then n +:= 13
  772. Xreturn corresp[n]
  773. Xend
  774. X
  775. Xprocedure d_augment()
  776. X#increment the day of the week
  777. X  current_day +:= 1
  778. X  if current_day = 8 then current_day := 1
  779. Xreturn
  780. Xend
  781. X
  782. Xprocedure augment()
  783. X#increments civil day, modifies month and year if necessary, stores in
  784. X#global variable cyr
  785. X  if cyr.day < 28 then
  786. X    cyr.day +:= 1 else
  787. X  if cyr.day = 28 then {
  788. X    if (cyr.mth ~= 2) | ((cyr.mth = 2) & isleap(cyr.yr)) then
  789. X      cyr.day := 29 else {
  790. X        cyr.mth := 3
  791. X    cyr.day  := 1}} else
  792. X  if cyr.day = 29 then {
  793. X    if cyr.mth ~= 2 then
  794. X      cyr.day := 30 else {
  795. X      cyr.mth := 3
  796. X      cyr.day := 1}} else
  797. X  if cyr.day = 30 then {
  798. X    if is_31(cyr.mth) then
  799. X      cyr.day := 31 else {
  800. X      cyr.mth +:= 1
  801. X      cyr.day := 1}} else {
  802. X      cyr.day := 1
  803. X      if cyr.mth ~= 12 then
  804. X        cyr.mth +:= 1 else {
  805. X        cyr.mth := 1
  806. X        cyr.yr +:= 1
  807. X        if cyr.yr = 0
  808. X      then cyr.yr := 1}}
  809. Xreturn
  810. Xend
  811. X
  812. Xprocedure is_31(n)
  813. X#civil months with 31 days
  814. Xreturn n = 1 | n = 3 | n = 5 | n = 7 | n = 8 | n = 10 | n = 12
  815. Xend
  816. X
  817. Xprocedure isleap(n)
  818. X#checks for civil leap year
  819. X  if n > 0 then
  820. Xreturn (n % 400 = 0) | ((n % 4 = 0) & (n % 100 ~= 0)) else
  821. Xreturn (n % 400 = -1) | ((n % 4 = -1) & (n % 100 ~= -1))
  822. Xend
  823. X
  824. Xprocedure j_augment()
  825. X#increments jewish day. months are numbered from nisan, adar sheni is 13.
  826. X#procedure fails at elul to allow determination of type of new year
  827. X  if jyr.day < 29 then
  828. X    jyr.day +:= 1 else
  829. X  if (jyr.day = 30) | always_29(jyr.mth) | ((jyr.mth = 8) & 
  830. X    (days_in_jyr % 5 ~= 0)) | ((jyr.mth = 9) & ((days_in_jyr = 353) |
  831. X    (days_in_jyr = 383))) then
  832. X    jyr.mth +:= jyr.day := 1 else
  833. X  if jyr.mth = 6 then fail else
  834. X  if ((jyr.mth = 12) & (days_in_jyr < 383)) | (jyr.mth = 13) then
  835. X    jyr.mth := jyr.day := 1 else
  836. X  jyr.day := 30
  837. Xreturn
  838. Xend
  839. X
  840. Xprocedure always_29(n)
  841. X#uncomplicated jewish months with 29 days
  842. Xreturn n = 2 | n = 4 | n = 10
  843. Xend
  844. X
  845. Xprocedure jyr_augment()
  846. X#determines the current time of lunation, using the ancient babylonian unit
  847. X#of 1/1080 of an hour. lunation of tishri determines type of year. allows
  848. X#for leap year. halaqim = parts of the hour
  849. Xlocal days, halaqim
  850. X  days := current_molad.day + 4
  851. X  if days_in_jyr <= 355 then {
  852. X    halaqim :=  current_molad.halaqim + 9516
  853. X    days := ((days +:= halaqim / 25920) % 7)
  854. X    if days = 0 then days := 7
  855. X    halaqim := halaqim % 25920} else {
  856. X    days +:= 1
  857. X    halaqim := current_molad.halaqim + 23269
  858. X    days := ((days +:= halaqim / 25920) % 7)
  859. X    if days = 0 then days := 7
  860. X    halaqim := halaqim % 25920}
  861. X  current_molad.day := days
  862. X  current_molad.halaqim := halaqim
  863. X#reset the global variable which holds the current jewish date
  864. X  jyr.yr +:= 1 #increment year
  865. X  jyr.day := 1
  866. X  jyr.mth := 7
  867. X  establish_jyr()
  868. Xreturn
  869. Xend
  870. X
  871. Xprocedure establish_jyr()
  872. X#establish the jewish year from get_rh
  873. Xlocal res
  874. X  res := get_rh(current_molad.day,current_molad.halaqim,no_lunar_yr(jyr.yr))
  875. X  days_in_jyr := res[2]
  876. X  current_day := res[1]
  877. Xreturn
  878. Xend    
  879. X
  880. Xprocedure isin1(i)
  881. X#the isin procedures are sets of years in the Metonic cycle
  882. Xreturn i = (1 | 4 | 7 | 9 | 12 | 15 | 18)
  883. Xend
  884. X
  885. Xprocedure isin2(i)
  886. Xreturn i = (2 | 5 | 10 | 13 | 16)
  887. Xend
  888. X
  889. Xprocedure isin3(i)
  890. Xreturn i = (3 | 6 | 8 | 11 | 14 | 17 | 0)
  891. Xend
  892. X
  893. Xprocedure isin4(i)
  894. Xreturn i = (1 | 2 | 4 | 5 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18)
  895. Xend
  896. X
  897. Xprocedure isin5(i)
  898. Xreturn i = (1 | 4 | 9 | 12 | 15)
  899. Xend
  900. X
  901. Xprocedure isin6(i)
  902. Xreturn i = (2 | 5 | 7 | 10 | 13 | 16 | 18)
  903. Xend
  904. X
  905. Xprocedure no_lunar_yr(i)
  906. X#what year in the metonic cycle is it?
  907. Xreturn i % 19
  908. Xend
  909. X
  910. Xprocedure get_rh(d,h,yr)
  911. X#this is the heart of the program. check the day of lunation of tishri
  912. X#and determine where breakpoint is that sets the new moon day in parts
  913. X#of the hour. return result in a list where 1 is day of rosh hashana and
  914. X#2 is length of jewish year
  915. Xlocal c,result
  916. X  c := no_lunar_yr(yr)
  917. X  result := list(2)
  918. X  if d = 1 then {
  919. X          result[1] := 2
  920. X                if (h < 9924) & isin4(c) then result[2] := 353 else
  921. X        if (h < 22091) & isin3(c) then result[2] := 383 else
  922. X        if (h > 9923) & (isin1(c) | isin2(c)) then result[2] := 355 else
  923. X        if (h > 22090) & isin3(c) then result[2] := 385
  924. X        } else
  925. X  if d = 2 then {
  926. X          if ((h < 16789) & isin1(c)) |
  927. X           ((h < 19440) & isin2(c)) then {
  928. X                                 result[1] := 2
  929. X                             result[2] := 355
  930. X                             } else
  931. X        if (h < 19440) & isin3(c) then  {
  932. X                                 result[1] := 2
  933. X                             result[2] := 385
  934. X                             } else
  935. X          if ((h > 16788) & isin1(c)) |
  936. X           ((h > 19439) & isin2(c)) then {
  937. X                                 result[1] := 3
  938. X                             result[2] := 354
  939. X                             } else
  940. X                if (h > 19439) & isin3(c) then  {
  941. X                                 result[1] := 3
  942. X                             result[2] := 384
  943. X                             }
  944. X        } else
  945. X  if d = 3 then {
  946. X          if (h < 9924) & (isin1(c) | isin2(c)) then {
  947. X                               result[1] := 3
  948. X                               result[2] := 354
  949. X                               } else
  950. X        if (h < 19440) & isin3(c) then {
  951. X                           result[1] := 3
  952. X                           result[2] := 384
  953. X                           } else
  954. X        if (h > 9923) & isin4(c) then {
  955. X                          result[1] := 5
  956. X                          result[2] := 354
  957. X                          } else
  958. X        if (h > 19439) & isin3(c) then {
  959. X                           result[1] := 5
  960. X                           result[2] := 383}
  961. X        } else
  962. X  if d = 4 then {
  963. X          result[1] := 5
  964. X        if isin4(c) then result[2] := 354 else
  965. X        if h < 12575 then result[2] := 383 else
  966. X        result[2] := 385
  967. X        } else
  968. X  if d = 5 then {
  969. X                if (h < 9924) & isin4(c) then {
  970. X                          result[1] := 5
  971. X                          result[2] := 354} else
  972. X        if (h < 19440) & isin3(c) then {
  973. X                           result[1] := 5
  974. X                           result[2] := 385
  975. X                           } else
  976. X        if (9923 < h < 19440) & isin4(c) then {
  977. X                              result[1] := 5
  978. X                              result[2] := 355
  979. X                              } else
  980. X        if h > 19439 then {
  981. X                    result[1] := 7
  982. X                          if isin3(c) then result[2] := 383 else
  983. X                            result[2] := 353
  984. X                  }
  985. X        } else
  986. X  if d = 6 then {
  987. X            result[1] := 7
  988. X            if ((h < 408) & isin5(c)) | ((h < 9924) & isin6(c)) then
  989. X                              result[2] := 353 else
  990. X            if ((h < 22091) & isin3(c)) then result[2] := 383 else
  991. X            if ((h > 407) & isin5(c)) | ((h > 9923) & isin6(c)) then
  992. X                              result[2] := 355 else
  993. X            if (h > 22090) & isin3(c) then result[2] := 385
  994. X            } else
  995. X  if d = 7 then    if (h < 19440) & (isin5(c) | isin6(c)) then {
  996. X                              result[1] := 7
  997. X                              result[2] := 355
  998. X                              } else
  999. X        if (h < 19440) & isin3(c) then {
  1000. X                           result[1] := 7
  1001. X                           result[2] := 385
  1002. X                           } else {
  1003. X                                  result[1] := 2
  1004. X                              if isin4(c) then
  1005. X                                result[2] := 353 else
  1006. X                            result[2] := 383}
  1007. Xreturn result
  1008. Xend
  1009. SHAR_EOF
  1010. # ============= itlib.icn ==============
  1011. echo "x - extracting itlib.icn (Text)"
  1012. sed 's/^X//' << 'SHAR_EOF' > itlib.icn &&
  1013. X########################################################################
  1014. X#    
  1015. X#    Name:    itlib.icn
  1016. X#    
  1017. X#    Title:    Icon termlib-type tools
  1018. X#    
  1019. X#    Author:    Richard L. Goerwitz
  1020. X#
  1021. X#    Date:    7/19/90 (version 1.3)
  1022. X#
  1023. X########################################################################
  1024. X#
  1025. X#  Copyright (c) 1990, Richard L. Goerwitz, III
  1026. X#
  1027. X#  This software is intended for free and unrestricted distribution.
  1028. X#  I place only two conditions on its use:  1) That you clearly mark
  1029. X#  any additions or changes you make to the source code, and 2) that
  1030. X#  you do not delete this message therefrom.  In order to protect
  1031. X#  myself from spurious litigation, it must also be stated here that,
  1032. X#  because this is free software, I, Richard Goerwitz, make no claim
  1033. X#  about the applicability or fitness of this software for any
  1034. X#  purpose, and expressly disclaim any responsibility for any damages
  1035. X#  that might be incurred in conjunction with its use.
  1036. X#
  1037. X########################################################################
  1038. X#
  1039. X#  The following library represents a series of rough functional
  1040. X#  equivalents to the standard Unix low-level termcap routines.  They
  1041. X#  are not meant as exact termlib clones.  Nor are they enhanced to
  1042. X#  take care of magic cookie terminals, terminals that use \D in their
  1043. X#  termcap entries, or, in short, anything I felt would not affect my
  1044. X#  normal, day-to-day work with ANSI and vt100 terminals.
  1045. X#
  1046. X#  Requires:  A unix platform & co-expressions.  Certainly the
  1047. X#  package could be altered for use with MS-DOS and other systems.
  1048. X#  Please contact me if advice on how to do this is needed.
  1049. X#
  1050. X#  setname(term)
  1051. X#    Use only if you wish to initialize itermlib for a terminal
  1052. X#  other than what your current environment specifies.  "Term" is the
  1053. X#  name of the termcap entry to use.  Normally this initialization is
  1054. X#  done automatically, and need not concern the user.
  1055. X#
  1056. X#  getval(id)
  1057. X#    Works something like tgetnum, tgetflag, and tgetstr.  In the
  1058. X#  spirit of Icon, all three have been collapsed into one routine.
  1059. X#  Integer valued caps are returned as integers, strings as strings,
  1060. X#  and flags as records (if a flag is set, then type(flag) will return
  1061. X#  "true").  Absence of a given capability is signalled by procedure
  1062. X#  failure.
  1063. X#
  1064. X#  igoto(cm,destcol,destline) - NB:  default 1 offset (*not* zero)!
  1065. X#    Analogous to tgoto.  "Cm" is the cursor movement command for
  1066. X#  the current terminal, as obtained via getval("cm").  Igoto()
  1067. X#  returns a string which, when output via iputs, will cause the
  1068. X#  cursor to move to column "destcol" and line "destline."  Column and
  1069. X#  line are always calculated using a *one* offset.  This is far more
  1070. X#  Iconish than the normal zero offset used by tgoto.  If you want to
  1071. X#  go to the first square on your screen, then input
  1072. X#  "igoto(getval("cm"),1,1)."
  1073. X#
  1074. X#  iputs(cp,affcnt)
  1075. X#    Equivalent to tputs.  "Cp" is a string obtained via getval(),
  1076. X#  or, in the case of "cm," via igoto(getval("cm"),x,y).  Affcnt is a
  1077. X#  count of affected lines.  It is only relevant for terminals which
  1078. X#  specify proportional (starred) delays in their termcap entries.
  1079. X#
  1080. X##########################################################################
  1081. X
  1082. X
  1083. Xglobal tc_table, tty_speed
  1084. Xrecord true()
  1085. X
  1086. X
  1087. Xprocedure check_features()
  1088. X
  1089. X    local in_params, yes_tabs, line
  1090. X    # global tty_speed
  1091. X
  1092. X    initial {
  1093. X    find("unix",map(&features)) |
  1094. X        er("check_features","unix system required",1)
  1095. X    find("o-expres",&features) |
  1096. X        er("check_features","co-expressions not implemented - &$#!",1)
  1097. X    system("/bin/stty tabs") |
  1098. X        er("check_features","can't set tabs option",1)
  1099. X    }
  1100. X
  1101. X    # clumsy, clumsy, clumsy, and probably won't work on all systems
  1102. X    in_params := open("/bin/stty 2>&1","pr") | 
  1103. X    (ospeed := &null, fail)
  1104. X    every line := !in_params do {
  1105. X    yes_tabs := find("tabs",line)
  1106. X    line ? {
  1107. X        tty_speed := (tab(find("speed")+5), tab(many(' ')),
  1108. X               integer(tab(many(&digits))))
  1109. X    }
  1110. X    }
  1111. X    close(in_params)
  1112. X    return "term characteristics reset; features check out"
  1113. X
  1114. Xend
  1115. X
  1116. X
  1117. X
  1118. Xprocedure setname(name)
  1119. X
  1120. X    # Sets current terminal type to "name" and builds a new termcap
  1121. X    # capability database (residing in tc_table).  Fails if unable to
  1122. X    # find a termcap entry for terminal type "name."  If you want it
  1123. X    # to terminate with an error message under these circumstances,
  1124. X    # comment out "| fail" below, and uncomment the er() line.
  1125. X
  1126. X    #tc_table is global
  1127. X    
  1128. X    check_features()
  1129. X
  1130. X    tc_table := maketc_table(getentry(name)) | fail
  1131. X    # er("setname","no termcap entry found for "||name,3)
  1132. X    return "successfully reset for terminal " || name
  1133. X
  1134. Xend
  1135. X
  1136. X
  1137. X
  1138. Xprocedure getname()
  1139. X
  1140. X    # Getname() first checks to be sure we're running under Unix, and,
  1141. X    # if so, tries to figure out what the current terminal type is,
  1142. X    # checking successively the value of the environment variable
  1143. X    # TERM, and then the output of "tset -".  Terminates with an error
  1144. X    # message if the terminal type cannot be ascertained.
  1145. X
  1146. X    local term, tset_output
  1147. X
  1148. X    check_features()
  1149. X
  1150. X    if not (term := getenv("TERM")) then {
  1151. X    tset_output := open("/bin/tset -","pr") |
  1152. X        er("getname","can't find tset command",1)
  1153. X    term := !tset_output
  1154. X    close(tset_output)
  1155. X    }
  1156. X    return \term |
  1157. X    er("getname","can't seem to determine your terminal type",1)
  1158. X
  1159. Xend
  1160. X
  1161. X
  1162. X
  1163. Xprocedure er(func,msg,errnum)
  1164. X
  1165. X    # short error processing utility
  1166. X    write(&errout,func,":  ",msg)
  1167. X    exit(errnum)
  1168. X
  1169. Xend
  1170. X
  1171. X
  1172. X
  1173. Xprocedure getentry(name)
  1174. X
  1175. X    # "Name" designates the current terminal type.  Getentry() scans
  1176. X    # the current environment for the variable TERMCAP.  If the
  1177. X    # TERMCAP string represents a termcap entry for a terminal of type
  1178. X    # "name," then getentry() returns the TERMCAP string.  Otherwise,
  1179. X    # getentry() will check to see if TERMCAP is a file name.  If so,
  1180. X    # getentry() will scan that file for an entry corresponding to
  1181. X    # "name."  If the TERMCAP string does not designate a filename,
  1182. X    # getentry() will scan /etc/termcap for the correct entry.
  1183. X    # Whatever the input file, if an entry for terminal "name" is
  1184. X    # found, getentry() returns that entry.  Otherwise, getentry()
  1185. X    # fails.
  1186. X
  1187. X    local termcap_string, f, getline, line, nm, ent1, ent2
  1188. X
  1189. X    termcap_string := getenv("TERMCAP")
  1190. X
  1191. X    if \termcap_string ? (not match("/"), pos(0) | tab(find("|")+1), =name)
  1192. X    then return termcap_string
  1193. X    else {
  1194. X
  1195. X    if find("/",\termcap_string)
  1196. SHAR_EOF
  1197. echo "End of  part 1"
  1198. echo "File itlib.icn is continued in part 2"
  1199. echo "2" > shar3_seq_.tmp
  1200. exit 0
  1201.  
  1202.    -Richard L. Goerwitz              goer%sophist@uchicago.bitnet
  1203.    goer@sophist.uchicago.edu         rutgers!oddjob!gide!sophist!goer
  1204.