home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / xcal / part08 < prev    next >
Encoding:
Text File  |  1993-12-22  |  56.5 KB  |  2,152 lines

  1. Newsgroups: comp.sources.x
  2. From: pc@hillside.co.uk (Peter Collinson)
  3. Subject: v21i083:  xcal - A calendar program for X, Part08/08
  4. Message-ID: <1993Dec21.161841.22372@sparky.sterling.com>
  5. X-Md4-Signature: c47fabb2c8856e2ccdfc2e606f886be2
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Hillside Systems, 61 Hillside Avenue, Canterbury, Kent CT2 8HA
  8. Date: Tue, 21 Dec 1993 16:18:41 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: pc@hillside.co.uk (Peter Collinson)
  12. Posting-number: Volume 21, Issue 83
  13. Archive-name: xcal/part08
  14. Environment: X11
  15. Supersedes: xcal: Volume 12, Issue 101
  16.  
  17. Xcal is a calendar program. For more details see Part 1 of this posting
  18.  
  19. Part 8 of 8
  20. --shar starts here--
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 8 (of 8)."
  28. # Contents:  xcal.man xcal_edit.c
  29. # Wrapped by pc@hillside on Wed Nov 17 11:24:37 1993
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'xcal.man' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'xcal.man'\"
  33. else
  34. echo shar: Extracting \"'xcal.man'\" \(25369 characters\)
  35. sed "s/^X//" >'xcal.man' <<'END_OF_FILE'
  36. X.TH xcal 1 "September 1990" "X Version 11 R5"
  37. X.SH NAME
  38. Xxcal \-  calendar with alarms and a notebook for X11
  39. X.SH SYNTAX
  40. X.B xcal
  41. X[
  42. X.B \-debug
  43. X][
  44. X.B \-alarmscan
  45. X][
  46. X.B \-format
  47. X.I fmt
  48. X][
  49. X.B \-editformat
  50. X.I fmt
  51. X][
  52. X.B \-stripformat
  53. X.I fmt
  54. X][
  55. X.B \-clocktick
  56. X.I tick
  57. X][
  58. X.B \-u
  59. X.I username
  60. X]
  61. X.SH DESCRIPTION
  62. X.de EX        \"Begin example
  63. X.ne 5
  64. X.if n .sp 1
  65. X.if t .sp .5
  66. X.nf
  67. X.ta +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u
  68. X..
  69. X.de EE
  70. X.fi
  71. X.if n .sp 1
  72. X.if t .sp .5
  73. X..
  74. X.I Xcal
  75. Xis an interactive calendar program.
  76. XThe user interface has several levels.
  77. XWhen started,
  78. X.I xcal
  79. Xdisplays today's date in a small command box
  80. Xthat is intended to sit on the screen as a companion to the
  81. X.I xclock
  82. Xprogram.
  83. XThe format of the command box may be altered using the resource manager, so you
  84. Xare not stuck with my preferred layout.
  85. XYou can set the time in the window too, if you wish (see the format resource).
  86. XAccess to further levels in
  87. X.I xcal
  88. Xis made by clicking a mouse button in the command box.
  89. XThe command box is split into several areas and clicking on one of these
  90. Xwill popup a window supporting a new function.
  91. X.PP
  92. XClicking with mouse button one on the question mark
  93. Xin the command box pops up a help window.
  94. X.I Xcal
  95. Xcomes with many help buttons.
  96. XWhen you are convinced they are no longer
  97. Xany use to you, they can all be turned off using an X resource.
  98. X.LP
  99. XA small button containing a `mouse' bitmap
  100. Xcan be pressed with mouse button one to inspect appointments for today.
  101. XThis generates a panel showing information from the calendar file for today and
  102. Xinformation from a set of seven daily files holding regular commitments.
  103. XThe panel also contains a text scratchpad, `the memo panel'.
  104. XThis allows the editing of a memo file.
  105. X.LP
  106. XThe calendar functions are accessed by clicking a mouse
  107. Xbuttons inside date portion of the command window.
  108. X.IP 1)
  109. XMouse button one pops up a calendar `strip' for the current month.
  110. XThe strip has some header lines and then one line per day of the month.
  111. XThe `line per day' display contains the day in the month and the
  112. Xday of the week.
  113. XToday may be highlighted specially \- the notion of Today alters at midnight.
  114. XThe strip has a help button which displays a description of the panel.
  115. XCommand buttons in the header line allows the user to bring up a strip
  116. Xfor the previous or the next month.
  117. X.IP 2)
  118. XPressing mouse button two in the date area will bring up a dialogue box
  119. Xwhich allows the user to select any month of any year (yes, September 1752
  120. Xis supported).
  121. XThe month may be input as month name or abbreviation, even though the
  122. Xprompt indicates a more restrictive format.
  123. X.IP 3)
  124. XPressing mouse button 3 in the date label causes the whole program to
  125. Xexit, a dialog box is used to ask the user for confirmation.
  126. X.LP
  127. XLike
  128. X.IR xcalendar ,
  129. Xdaily events are stored in set of files, one for each day.
  130. XIf the file exists when the strip is started,
  131. Xits data is displayed as the label in the command
  132. Xbutton on the right-hand side of the month strip.
  133. XThe file is created and edited by entering a simple text editor
  134. X(the standard text widget) which is started
  135. Xby pressing the right hand side of the appropriate day line in the strip.
  136. XYou can also add data to the file by selecting a string on the
  137. Xscreen and clicking with
  138. Xthe middle button on the right-hand side of the month strip.
  139. XThe string is appended to the file for the day.
  140. XThis short-hand allows one entry to be loaded into several day files.
  141. X.LP
  142. XThe width of the
  143. Xmonth strip is computed from the width of the header. 
  144. XUsers who
  145. Xwish to display a wider strip to show more of the stored information
  146. Xshould widen the strip using the
  147. X.I minStripWidth
  148. Xresource (see below).
  149. X.LP
  150. XThe colours and fonts used in the strip is controllable by resources.
  151. XThe widget that comprises each line in the strip is tagged with the short
  152. Xform name of the day, so it's easy to vary the strip display showing weekends
  153. Xdifferently from the weekdays.
  154. X.LP
  155. XData files are stored in a directory usually called
  156. X.B Calendar
  157. Xunder the user's home directory.
  158. XEach file is stored in a subdirectory containing all the data
  159. Xfor a particular year.
  160. XThis is incompatible with 
  161. X.IR xcalendar ,
  162. Xthe user may specify that the compatibility should be maintained.
  163. X.LP
  164. XAlarms are supported by
  165. X.IR xcal .
  166. XWhen a line in the data file starts with a digit, it is
  167. Xassumed to be a time specification and a candidate for an alarm.
  168. XThe line contains a string giving the alarm time and a text string
  169. Xdisplayed in a dialogue alarm box that pops up when the alarm fires.
  170. XYou can also arrange for countdown alarms to fire, so that you can
  171. Xbe told that something is about to happen.
  172. XThese dialogue boxes will automatically go away after two minutes, unless the
  173. X`Stick' button is pressed glueing the box onto the screen.
  174. XThe box can be made to go away at any time by hitting the `Unpin' button.
  175. X.LP
  176. XWhen specifying alarms,
  177. X.I Xcal
  178. Xtries to be liberal about the times that it understands.
  179. XTime specifications are: h, hh, hhmm, hmm, hh:mm, h:mm, hh.mm, h.mm;
  180. Xall of these may be optionally followed by an am/pm indicator \- one
  181. Xof: A, a, AM, am, Am, aM, P, p, PM, pm, Pm, pM.
  182. XTimes must always be followed by at least one space or tab.
  183. XSome legal examples are:
  184. X.br
  185. X.nf
  186. X    12:00 Lunch - Meet Joe at Burger King
  187. X    14.30 Meeting in the cafeteria
  188. X    2:30p Ring Mark
  189. X    7pm Pizza
  190. X.fi
  191. X.LP
  192. XYou can make a time like 2:30 mean 14:30 by setting the resource
  193. X.I AlarmWarp
  194. Xto be true.
  195. XIf this is the case, an alarm hour will be promoted to a PM time if it is found
  196. Xto be between the range of
  197. Xzero and the value of the resource
  198. X.IR minAlarmWarp .
  199. X.LP
  200. X.I Xcal
  201. Xalso supports timed command execution from the data file.
  202. XTo trigger a command, the data part of the line starts
  203. Xwith an exclamation mark, eg:
  204. X.br
  205. X    4.30pm !xmessage -message 'ring home'
  206. X.LP
  207. XThe exclamation mark can also be replaced by the string `%cron'.
  208. XIt is also possible to make 
  209. X.I xcal
  210. Xexecute a command whenever an alarm is triggered, see the
  211. X.I Cmd
  212. Xresource below.
  213. X.LP
  214. XThe memo function of
  215. X.I Xcal
  216. Xis accessed by pressing the non-date portion of the command window.
  217. XThis shows a bitmap diagram of three mouse buttons.
  218. XClicking the left mouse button in this area brings up a complex panel,
  219. Xclicking on the button again will pop it back down again.
  220. XThe top half of the panel displays the information held in the diary
  221. Xfor today; pressing the Edit button here will start an edit box for today.
  222. XThe next section of the panel displays the information held in the
  223. Xweekly files.
  224. XAgain you cannot directly change the text in this area, you must
  225. Xpress on the Edit button to bring up a strip enabling you to
  226. Xchange things.
  227. XThe bottom portion of the panel is an edit window displaying the contents
  228. Xof a file usually called `memo' in the Calendar directory.
  229. XThe idea of this panel is to allow you to access your current information
  230. Xin one button click.
  231. X.LP
  232. XIt is obviously possible to change
  233. X.IR Xcal 's
  234. Xdata files without using the inbuilt text widget editor.
  235. XIn general,
  236. X.I Xcal
  237. Xwill not notice this.
  238. XEditing random day files with a standard text editor will not
  239. Xchange the contents of any displayed strips until the strips are
  240. Xpopped down and up again.
  241. X.I Xcal
  242. Xknows what days have been altered when the text widget is used to
  243. Xedit the day files, and will reflect any change immediately into
  244. Xthe displayed strips.
  245. X.LP
  246. XYou can make 
  247. X.I Xcal
  248. Xtake notice of today's date file and the current memo file.
  249. XThe `Update' resource sets a polling time in seconds.
  250. XWhen the clock fires and today's file has been altered,
  251. Xthe alarm list is rebuilt from the current date file
  252. Xand the memo panel is updated.
  253. XThe bottom part of the memo panel is also updated if the `memo'
  254. Xfile has been altered on the clock tick.
  255. X.SH OPTIONS
  256. X.LP
  257. XVersion 4 of
  258. X.I Xcal
  259. Xpermits one user to view another's calendar by giving the
  260. X.I \-u
  261. Xoption followed by the user's login name.
  262. XThe user's calendar storage area
  263. Xis assumed to be called `Calendar' in their home directory.
  264. XThe facilities are somewhat rudimentary.
  265. XFirst, the main date box will have the user's login name appended to the
  266. Xdate format string.
  267. XWhen a month strip is generated, you will be given read-only access to their
  268. Xcalendar files, assuming that the file permissions allow you to read them.
  269. XThis is intended to be one step better than using
  270. X.I cat
  271. Xon their calendar files.
  272. X.LP
  273. XThe
  274. X.I \-debug
  275. Xswitch causes contents of the initial date window to be incremented very
  276. Xfrequently, this allows some testing of the program.
  277. X.LP
  278. XThe
  279. X.I \-alarmscan
  280. Xswitch prints debugging information about the alarm system on standard output.
  281. X.LP
  282. XThe argument following the
  283. X.I \-format
  284. Xis a date format
  285. Xused to display dates in the top level window
  286. X(see below, the
  287. X.I Format
  288. Xresource).
  289. XChanging this to include a time format will make
  290. X.I xcal
  291. Xdisplay a clock in your top level window.
  292. X.LP
  293. XThe argument following the
  294. X.I \-stripfmt
  295. Xargument is a date format used to display month names and years in the monthly
  296. Xcalendar strip.
  297. X(see the resource
  298. X.IR StripFmt ).
  299. X.LP
  300. XSimilarly, the
  301. X.I \-editfmt
  302. Xargument is the format for dates used in an edit window
  303. X(see the
  304. X.I Editfmt
  305. Xresource).
  306. X.LP
  307. XThe
  308. X.I \-clocktick
  309. Xargument is used to set the clock update time of the main date window,
  310. Xshould a time be displayed as well as the date.
  311. XSee the
  312. X.I Clocktick
  313. Xresource.
  314. X.SH RESOURCES
  315. XAs with all standard X applications,
  316. X.I xcal
  317. Xmay be customised through 
  318. Xentries in the resource manager.
  319. XIt is a serious mistake to install
  320. X.I Xcal
  321. Xwithout putting the resource initialisation file 
  322. X.I Xcal
  323. Xin 
  324. X.IR /usr/lib/X11/app-defaults .
  325. XResource class names are listed below;
  326. Xresource instance names are identical, except the first letter is in
  327. Xlower case.
  328. XThe following resource manager entries are defined:
  329. X.LP
  330. X.TP "\w'ReverseVideoMarkNNN'u"
  331. X.B Debug
  332. XIf True enables accelerated time.
  333. XAlarms will not function correctly.
  334. XDefault: False.
  335. X.TP
  336. X.B OtherUser
  337. Xthe name of the user whose calendar files will be inspected.
  338. XThis is usually set by the
  339. X.B \-u
  340. Xoption.
  341. X.TP
  342. X.B AlarmScan
  343. XIf True enables printing of alarm related debugging information
  344. Xto the standard output.
  345. XDefault: False.
  346. X.TP
  347. X.B ReverseVideo
  348. XIf true display the output in reverse video.
  349. XDefault: False.
  350. X.TP
  351. X.B Format
  352. XThis is a format string used to create the contents of the top command
  353. Xbutton and the memo box.
  354. XThe format is aimed at the system routine:
  355. X.IR strftime .
  356. XI have chosen to use the system routine because it makes it easier for
  357. Xnon-english language sites to generate their own formats.
  358. XHowever, this means that the names used for months and days may not be compatible
  359. Xwith the ones set in the resources below.
  360. XAny characters in the format string are passed to the output unchanged
  361. Xunless they specify a format.
  362. XFormat letters are preceded by a `%' character and can be found in the
  363. Xdocumentation for
  364. X.I strftime
  365. Xon your system.
  366. XThe SunOS 4.1.3 routine supports:
  367. X.EX
  368. X%%    same as %
  369. X%a    day of week using abbreviated name
  370. X%A    day of week using full weekday names
  371. X%b    (%h) month, using locale's abbreviated names
  372. X%B    month, using locale's full names
  373. X%c    date and time as %x %X
  374. X%C    date and time, in local long-format date and
  375. X    time representation
  376. X%d    day of month (01-31)
  377. X%D    date as %m/%d/%y
  378. X%e    day of month (1-31; single digits are preceded  by a blank)
  379. X%H    hour (00-23)
  380. X%I    hour (00-12)
  381. X%j    day number of year (001-366)
  382. X%k    hour (0-23; single digits are preceded by a blank)
  383. X%l    hour (1-12; single digits are preceded by a blank)
  384. X%m    month number (01-12)
  385. X%M    minute (00-59)
  386. X%n    same as \en
  387. X%p    local equivalent of AM or PM
  388. X%r    time as %I:%M:%S %p
  389. X%R    time as %H:%M
  390. X%S    seconds (00-59)
  391. X%t    same as \et
  392. X%U    week number of year (01-52), Sunday is the first day of the week
  393. X%W    week number of year (01-52), Monday is the first day of the week
  394. X%x    date, using locale's date format
  395. X%X    time, using locale's time format
  396. X%y    year within century (00-99)
  397. X%Y    year, including century (fore example, 1988)
  398. X%Z    time zone abbreviation
  399. X.EE
  400. XThe default is "%A %d %B %Y", printing the day, the date, the month and the
  401. Xfull year.
  402. XI prefer to use "%A %e %B %Y", but this does not seem to be portable to
  403. Xdifferent systems.
  404. XThe format string is scanned to determine the update frequency that
  405. Xis needed to maintain a correct date image.
  406. XThe default needs updating every 24 hours, if you insert an AM/PM format
  407. Xthen the strip will be updated every 12 hours.
  408. XAdding an hour specification will cause an update every hour and specifying
  409. Xminutes or seconds will cause appropriate behaviour.
  410. X.TP
  411. X.B ClockTick
  412. XIf you specify a second hand in the main
  413. Xdate string and only want it updated every 30 seconds (say)
  414. Xthen setting the ClockTick resource to 30 will force an update for that period.
  415. XDefault: 0 (derived from the
  416. X.I Format
  417. Xstring).
  418. X.TP
  419. X.B StripFmt
  420. Xis used to format the date line at the top of each strip.
  421. XThis uses an internal version of the
  422. X.I strftime
  423. Xroutine that only
  424. Xsupports format characters relating to months, years and days.
  425. XThe supported format characters are: %A, %a, %B, %b, %h, %D, %d, %e, %m, %n,
  426. X%t, %x, %y and %%.
  427. XLong/short day and month names are taken from the resources.
  428. XDefault: "%B %y".
  429. X.TP
  430. X.B EditFmt
  431. Xprovides the format string for any edit window.
  432. XThis uses the same code as
  433. X.BR StripFmt .
  434. XDefault: "%A %d %B %Y".
  435. XAgain, I prefer to use "%A %e %B %Y".
  436. X.TP
  437. X.B MarkToday
  438. XIf True then highlight today.
  439. XDefault True.
  440. X.TP
  441. X.B TodayBackground
  442. Xthe background colour when marking, default Black.
  443. X.TP
  444. X.B TodayForeground
  445. Xthe foreground colour when marking today, default White.
  446. X.TP
  447. X.B FontToday
  448. XToday may be marked by using a special font, if this is desired the
  449. Xfont is given by this resource.
  450. XDefault is to use the default font.
  451. X.TP
  452. X.B Directory
  453. XThe name of the directory under the home directory
  454. Xwhere the day files are stored.
  455. XDefault: Calendar.
  456. X.TP
  457. X.B XcalendarCompat
  458. XIf true then subdirectories are not created in the Calendar directory.
  459. XThis flag is not relevant when files are being read, so users
  460. Xcan use both programs with existing data files.
  461. XDefault: False.
  462. X.TP
  463. X.B GiveHelp
  464. XIf True than access to the help information is given.
  465. XIf False, help buttons disappear returning screen real-estate to the user.
  466. XYou should resist setting this to False in the default resources file.
  467. XDefault: True.
  468. X.TP
  469. X.B HelpFromFile
  470. XThe
  471. X.I Xcal
  472. Xprogram will usually have help strings compiled into it.
  473. XThese are in English and it may be desirable to use help data in other languages.
  474. XIf this resource is true, it forces
  475. X.I Xcal
  476. Xto look in a data file for the help strings.
  477. XDefault: False.
  478. X.TP
  479. X.B HelpFile
  480. Xgives the name of the file used as a database for the help system,
  481. Xaccessed when
  482. X.B HelpFromFile
  483. Xis True.
  484. XDefault: /usr/lib/X11/XCal.help.
  485. X.TP
  486. X.B InitialCalendar
  487. XIf True then the calendar for this month is automatically displayed on
  488. Xstartup.
  489. XIf False, the calendar is not automatically displayed.
  490. XDefault: False.
  491. X.TP
  492. X.B InitialEdit
  493. XIf True then an edit window for today is automatically displayed on
  494. Xstartup if a file exists for today's date.
  495. XIf False, the edit window is not automatically displayed.
  496. XDefault: False.
  497. X.TP
  498. X.B InitialMemo
  499. XIf True then the memo window is automatically displayed on startup.
  500. XDefault: False.
  501. X.TP
  502. X.B UseWmTitle
  503. XIf True display the month and the year at the head of each strip.
  504. XThis information is duplicated if your window manager uses titles
  505. Xso it is nice to be able to turn it off.
  506. XDefault: True.
  507. X.TP
  508. X.B TextBufferSize
  509. Xthe maximum number of bytes which we are prepared to deal with in an
  510. Xedit window.
  511. XDefault: 2048 bytes.
  512. X.TP
  513. X.B Alarms
  514. Xwhether or not to enable the alarm system.
  515. XDefault: True.
  516. X.TP
  517. X.B ExecAlarms
  518. Xif the alarm system is active,
  519. Xwhether or not to invoke timed-execution commands.
  520. XDefault: True.
  521. X.TP
  522. X.B Update
  523. XWhen scanning for alarms in the current day file
  524. X.I Xcal
  525. Xinspects it at program startup time and also when it is edited using the
  526. Xnormal built-in editing mechanism.
  527. XHowever, if some external program changes t file
  528. X.I xcal
  529. Xwill not see the new contents and new alarms will not be set.
  530. XSetting this resource to non-zero will force 
  531. X.I xcal
  532. Xto scan the file every `update' seconds
  533. Xlooking for alterations in size and modification date.
  534. XWhen it detects that the file is altered, then
  535. Xit will rebuild the internal alarm list.
  536. XDefault: zero.
  537. X.TP
  538. X.B Nbeeps
  539. XWhen an alarm window is popped up, it is accompanied by `Nbeeps' beeps.
  540. XDefault: 3.
  541. X.TP
  542. X.B Volume
  543. XControl the loudness of the beep. Default: 50.
  544. X.TP
  545. X.B Cmd
  546. XThis resource contains a command that is executed by calling the shell
  547. Xwhen every alarm is triggered.
  548. XThe command is passed the contents of the data line as one argument.
  549. X.TP
  550. X.B Countdown
  551. Xcontains a comma separated string of numbers; for example: 10,5,0.
  552. XThe string allows the user to customise warning alarms: so in the
  553. Xexample, alarm boxes will be displayed 10 minutes before the stated time,
  554. X5 minutes before the stated time and exactly on the stated time.
  555. XCommands lines in the data prefaced by a `!' will always be triggered
  556. Xexactly at the stated time.
  557. XDefault: 10,0.
  558. X.TP
  559. X.B Autoquit
  560. XEach dialogue box containing an alarm message contains an `Unpin' button
  561. Xallowing the user to remove the message from the screen by using mouse button one.
  562. XAdditionally, the message box can remove itself from the screen after
  563. Xa specified period, this resource gives that timeout in seconds.
  564. XIf the resource is set to zero, then the user is always forced to take
  565. Xexplicit action to remove the box.
  566. XDefault: 120, alarm boxes disappear after 2 mins.
  567. X.TP
  568. X.B Alarmleft
  569. Xcontains a
  570. X.I printf
  571. Xstring that is displayed in the label at the top
  572. Xof an alarm box when countdown is in operation and
  573. Xthere is some time before the stated time.
  574. XThe time before the stated time is supplied as the second argument to printf.
  575. XDefault: ``%d minutes before...''
  576. X.TP
  577. X.B Alarmnow
  578. Xcontains the 
  579. X.I printf
  580. Xstring that is displayed in the label at the top
  581. Xof an alarm box when the stated time is reached.
  582. XDefault: ``Time is now...''.
  583. X.TP
  584. X.B UseMemo
  585. Xenables the use of the memo feature.
  586. XThis defaults to ``True'', but is present to allow users to make 
  587. X.I XCal
  588. Xhave as it used to.
  589. X.TP
  590. X.B MemoLeft
  591. Xaffects the placing of the memo button in the top level date window.
  592. XThe default is `True' meaning that the button box is placed on the left
  593. Xof the date portion.
  594. XSetting this to `False' will place the button box to the right of the
  595. Xdate portions.
  596. X.TP
  597. X.B MemoFile
  598. Xgives the name of the memo file within the Calendar directory.
  599. XThe default is `memo'.
  600. X.TP
  601. X.B MaxDisplayLines
  602. Xcontrols the maximum number of text lines that can placed in the
  603. Xtop half of the memo panel.
  604. XThe top hald will normally size to the number of lines in the diary
  605. Xfile for the day, unless the number of lines exceed the value in
  606. Xthis resource.
  607. XThis ensures that today's events do not dominate the memo panel.
  608. XDefault: 5 lines.
  609. X.TP
  610. X.B MaxStripHeight
  611. Xcontrols the maximum height of a strip.
  612. XA scroll bar will be added into the date part of the scrip of the contents
  613. Xare larger than this number.
  614. XIf unset, this defaults to the height of the screen.
  615. XDefault: unset.
  616. X.TP
  617. X.B MinStripWidth
  618. XThe width of month strips are set by the top line, which usually
  619. Xdisplays the month and year.
  620. XThe whole strip can be widened from this default value by setting this
  621. Xresource to be non-zero.
  622. XDefault: zero (i.e. off).
  623. X.TP
  624. X.B January
  625. X.B February
  626. Xand so on.
  627. XThe names of the long form of the month name.
  628. X.TP
  629. X.B Jan
  630. X.B Feb
  631. Xand so on.
  632. XA short form of the month name - done this way because I doubt that
  633. Xwriting with %3s works in all languages.
  634. XChanging this resource means that the data file will no longer be
  635. Xcompatible with
  636. X.I xcalendar .
  637. X.TP
  638. X.B Sunday
  639. X.B Monday
  640. Xand so on.
  641. XThe
  642. X.I long
  643. Xnames of the days: Sunday, Monday etc.
  644. XThese are used in titles: the top level widget, the title of an edit window
  645. Xand the memo frame.
  646. X.TP
  647. X.B Sun
  648. X.B Mon
  649. Xand so on.
  650. XThe short names of the days \- used in date strips.
  651. X.TP
  652. X.B Private
  653. XContains the string `Private calendar entry' and is used when the \-u option
  654. Xis in force. It is displayed when a calendar file entry is unreadable
  655. Xby the caller.
  656. X.TP
  657. X.B Alarmleft
  658. XContains the string `%d minutes before'.
  659. X.TP
  660. X.B Alarmnow
  661. XContains the string `Time is now...'.
  662. X.TP
  663. X.B Already
  664. XContains the string `Already editing %d %B %Y'
  665. XI prefer to use `Already editing %e %B %Y'.
  666. X.TP
  667. X.B AlreadyWeekly
  668. XContains the string `Already editing %A'.
  669. X.SH "PANEL MAP"
  670. X.PP
  671. X.I Xcal
  672. Xmakes extensive use of the resource manager.
  673. XThe user needs to know the names of the various panels and widgets which
  674. Xcomprise the application.
  675. X.LP
  676. X.EX
  677. XXCal                Toplevel application
  678. X    form            Form containing two buttons
  679. X        today        Memo Command button
  680. X        date        Strip Command button
  681. X        mainHelp        Optional main help button
  682. X.EE
  683. X.LP
  684. XThen we have various popups.
  685. XThe Calendar Strip is:
  686. X.EX
  687. X"Mon Year"            the popup shell
  688. X    Month            panel containing the strip
  689. X        header        label containing month and year
  690. X        action        form containing < quit > buttons 
  691. X            back    command containing < - last month
  692. X            quit    command containing exit button
  693. X            next    command containing > - next month
  694. X        help        command generating help
  695. X    viewport            viewport permitting scrolling of the
  696. X    data            data widget
  697. X        "DDD"        form containing day button (lots of these)
  698. X                these are named for the short days of the week
  699. X            label    label containing dd DDD, day of the month
  700. X                and day of the week
  701. X            info    command containing the file data
  702. X.EE
  703. X.LP
  704. XNote that each day button is named for the day of the week, so that
  705. Xweekends can be highlighted specially using the standard resources.
  706. X.LP
  707. XThe weekly popup strip is:
  708. X.EX
  709. Xweekly                the popup shell
  710. X    weekly            panel containing the strip
  711. X        header        label containing the title
  712. X        action        form containing quit and help
  713. X            quit    command containing exit button
  714. X            help    command generating help
  715. X    viewport        viewport permitting scrolling of the
  716. X    data            data widget
  717. X        shortday    form containing days
  718. X            label    label containing day of the week
  719. X            info    command containing the file data
  720. X.EE
  721. X.LP
  722. XThe Edit Window is:
  723. X.EX
  724. Xedit                the popup shell
  725. X    panel            the panel inside the shell
  726. X        title        the form containing the first line
  727. X            quit    the exit button
  728. X            save    the save button
  729. X            help    the help button
  730. X            date    the date string
  731. X        text        the text widget for editing
  732. X        
  733. X.EE    
  734. X.LP
  735. XThe Help Window is:
  736. X.EX
  737. Xhelp                the popup shell
  738. X    helpPanel            the panel inside the shell
  739. X        helpForm        the form containing the title line
  740. X            quit    the exit button
  741. X        helpText        the text widget showing the information
  742. X.EE
  743. X.LP
  744. XThe Alarm Window is:
  745. X.EX
  746. Xalarm                the popup shell
  747. X    alarmPanel        the panel inside the shell
  748. X        alarmForm    form for top line
  749. X            alarmQuit    the exit button
  750. X            alarmHold    the hold button
  751. X            alarmTitle    the title on the alarm window
  752. X        alarmText    the text widget for displaying
  753. X.EE
  754. X.LP
  755. XThe Memo Window is:
  756. X.EX
  757. Xmemo                the popup shell
  758. X    memoPanel        the panel inside the shell
  759. X        title        Top line form widget
  760. X            quit    the exit button
  761. X            edit    edit button - edit today's info
  762. X            help    the help button
  763. X            date    display today's date
  764. X        display        text from today's date file
  765. X        weeklyMemo    form for the Memo title line
  766. X            weeklyEdit    Edit button
  767. X            weeklyTitle    Title area
  768. X        display        text from today's weekly file
  769. X        memoMiddle    Middle line form widget
  770. X            save    Save button
  771. X            memoTitle    text title of middle line
  772. X        memoText    Text widget showing memo file
  773. X.EE
  774. X.LP
  775. XThe Middle button date selection popup is:
  776. X.EX
  777. Xquestion                the popup shell
  778. X    newdate            the dialog widget
  779. X        ok        the OK button
  780. X        cancel        the cancel button
  781. X.EE
  782. X.LP
  783. XThe Right button exit selection popup is:
  784. X.EX
  785. Xquestion                the popup shell
  786. X    exit            the dialog widget
  787. X        yes        the yes button
  788. X        no        the no button
  789. X.EE
  790. X.LP
  791. XAn error is shown when a multiple attempts are made to edit the same day file.
  792. X.EX
  793. Xquestion                the popup shell
  794. X    noedit            the dialog widget
  795. X        ok        the OK button
  796. X.EE
  797. X.LP
  798. XA dialog box is popped up when an attempt is made to exit from an editing
  799. Xbox without saving the file.
  800. X.EX
  801. Xcheck                the dialog widget
  802. X    yes            the yes button
  803. X    no            the no button
  804. X.EE
  805. X.SH FILES
  806. X.PP
  807. X$HOME/Calendar/\(**
  808. X.LP
  809. X.TP "\w'xc<dd><Mon><Year>  'u"
  810. Xxc<dd><Mon><Year>
  811. XA data file is day, Month in three letter format and the year.
  812. X.TP
  813. Xxy<Year>
  814. XA year directory.
  815. X.TP
  816. Xxw<Day>
  817. XA data file for the weekly code, one per day.
  818. X.TP
  819. Xmemo
  820. XThe memo file.
  821. X.LP
  822. XThe standard resource database can be found in /usr/lib/X11/app-defaults/Xcal.
  823. XAssuming that this is where the system admin installed it.
  824. X.PP
  825. X.SH SEE ALSO
  826. Xxrdb(1), xcalev(1), xcalpr(1), xcal_cal(1)
  827. X.PP
  828. X.SH BUGS
  829. XThere should be some way of removing several edit windows from the screen
  830. Xat once.
  831. X.LP
  832. XSetting an alarm 1 minute in the future may not work.
  833. X.LP
  834. XCountdown does not work in the early hours of the morning, if you have a
  835. Xten minute countdown and an alarm set at 0005 \- then you will not get
  836. Xwarning at 2325.
  837. X.LP
  838. XAlarms set at 0000 probably won't work.
  839. X.SH AUTHOR
  840. X.LP
  841. XCopyright 1989,1990,1993 by Peter Collinson, Hillside Systems
  842. XAll rights reserved.
  843. X.PP
  844. XThis product includes software developed by the University of
  845. XCalifornia, Berkeley and its contributors.
  846. X.PP
  847. XAt one time, much of the
  848. X.B xcalendar
  849. Xprogram was plundered to create
  850. X.B xcal ;
  851. Xauthor is: Roman J. Budzianowski, MIT Project Athena
  852. X.PP
  853. XThanks to Ed Gould, Mt Xinu for the support for the
  854. X.IR calendar (1)
  855. Xprogram.
  856. XThanks to Mark Majhor, Sequent for the basis of the alarm code.
  857. XThanks to Rod Whitby, Austek Microsystems Pty. Ltd., Australia
  858. Xfor the ideas of the Stick/Unpin code for alarms and for prompting
  859. Xme to add the memo code.
  860. XThanks to Miles O'Neal from Pencom for revising the help code to be
  861. Xa little more `X', although this was later revised to use files.
  862. X.LP
  863. XThere are a number of other people who have sent in revisions, some I
  864. Xhave used, some I have not.
  865. XThanks anyway.
  866. END_OF_FILE
  867. if test 25369 -ne `wc -c <'xcal.man'`; then
  868.     echo shar: \"'xcal.man'\" unpacked with wrong size!
  869. fi
  870. # end of 'xcal.man'
  871. fi
  872. if test -f 'xcal_edit.c' -a "${1}" != "-c" ; then 
  873.   echo shar: Will not clobber existing file \"'xcal_edit.c'\"
  874. else
  875. echo shar: Extracting \"'xcal_edit.c'\" \(27722 characters\)
  876. sed "s/^X//" >'xcal_edit.c' <<'END_OF_FILE'
  877. X#ifndef lint
  878. Xstatic char    *sccsid = "@(#)xcal_edit.c    3.37 (Hillside Systems) 11/8/93";
  879. Xstatic char    *copyright = "@(#)Copyright 1989,1990,1993 Peter Collinson, Hillside Systems";
  880. X#endif                /* lint */
  881. X/***
  882. X
  883. X* module name:
  884. X    xcal_edit.c
  885. X* function:
  886. X    Deal with editable days
  887. X    This is derived from xcalendar's view of how to store things
  888. X* history:
  889. X    Written November 1989
  890. X    Peter Collinson
  891. X    Hillside Systems
  892. X* (C) Copyright: 1989 Hillside Systems/Peter Collinson
  893. X
  894. X    For full permissions and copyright notice - see xcal.c
  895. X***/
  896. X#include <stdio.h>
  897. X#include <ctype.h>
  898. X#include <pwd.h>
  899. X#include <X11/Intrinsic.h>
  900. X#include <X11/Xos.h>
  901. X#include <X11/StringDefs.h>
  902. X#include <X11/Shell.h>
  903. X#include <X11/Xaw/AsciiText.h>
  904. X#include <X11/Xaw/Text.h>
  905. X#include <X11/Xaw/Command.h>
  906. X#include <X11/Xaw/Label.h>
  907. X#include <X11/Xaw/Paned.h>
  908. X#include <X11/Xaw/Form.h>
  909. X#include <X11/Xaw/Dialog.h>
  910. X#include "xcal.h"
  911. X#include <sys/stat.h>
  912. X#if defined(NeXT) || defined(mips)
  913. X#include <sys/fcntl.h>
  914. X#include <sys/dir.h>
  915. X#include <sys/dirent.h>
  916. X#else
  917. X#include <dirent.h>
  918. X#endif
  919. X
  920. X#define argLD(N,V) { XtSetArg(args[nargs], N, V); nargs++; }
  921. X
  922. Xtypedef struct editline {
  923. X    struct editline *ed_next;    /* Pointer to next */
  924. X    struct meWrap  *ed_meWrap;    /* Pointer to head of the chain */
  925. X    Cardinal        ed_day;        /* What day we are */
  926. X    Widget          ed_popup;    /* widget of editor popup */
  927. X    Widget          ed_quit;    /* widget of quit button */
  928. X    Widget          ed_save;    /* widget of save button */
  929. X    Widget          ed_text;    /* the text area */
  930. X    Cardinal        ed_size;    /* size of the buffer */
  931. X    char           *ed_data;    /* pointer to malloc'ed data buffer */
  932. X} EditLine;
  933. X
  934. Xtypedef struct meWrap {
  935. X    struct meWrap  *mw_next;
  936. X    String          mw_dir;        /* name of the directory */
  937. X    Boolean         mw_useTopDir;    /* have found some data in the top dir */
  938. X    MonthEntry      mw_me;        /* what the external world sees */
  939. X    Instance       *mw_list;    /* list of toplevel widget for the */
  940. X                    /* current set of displayed strips */
  941. X    EditLine       *mw_ed;        /* data being edited */
  942. X} MeWrap;
  943. X
  944. X#define    mw_year    mw_me.me_year
  945. X#define mw_month mw_me.me_month
  946. X#define mw_have    mw_me.me_have
  947. X
  948. X#define    StripType(mw)    (mw->mw_me.me_type)
  949. X
  950. Xstatic MeWrap  *WrapBase;        /* base of the list */
  951. Xstatic MeWrap  *WrapEnd;        /* the last one in the list */
  952. X
  953. Xchar           *MapStem;        /* pointer to the string which is */
  954. X                    /* where the map data is stored */
  955. X
  956. XBoolean         FoundCalendarDir;    /* whether the Calendar directory */
  957. X                    /* exists */
  958. X
  959. Xstatic XtCallbackRec callbacks[] = {
  960. X    {NULL, NULL},
  961. X    {NULL, NULL}
  962. X};
  963. X#define ClearCallbacks() memset((caddr_t)callbacks, '\0', sizeof (callbacks))
  964. X
  965. X/*
  966. X * Routine specs
  967. X */    
  968. Xstatic void    MakeMapStem();
  969. Xstatic MeWrap  *NewMeWrap();
  970. Xstatic MeWrap  *MeWrapSearch();
  971. Xstatic void     DeRegisterMonth();
  972. Xstatic Boolean  WriteCalendarFile();
  973. Xstatic Boolean  WriteWeeklyFile();
  974. Xstatic void     DeleteCalendarFile();
  975. Xstatic int    EditCheck();
  976. Xstatic void     SetAllButtons();
  977. Xstatic void     TextChanged();
  978. Xstatic void    UpdateDayDetails();
  979. Xstatic void     FinishEditing();
  980. Xstatic void     CleanEditPanel();
  981. Xstatic void     CheckExit();
  982. Xstatic void     CheckDia();
  983. Xstatic void     YesCheck();
  984. Xstatic void     NoCheck();
  985. Xstatic int      DayMatch();
  986. Xstatic void    SaveEdits();
  987. Xvoid            StartDayEditor();
  988. Xvoid            Fatal();
  989. X
  990. X
  991. X
  992. X/*
  993. X * Fire up the month entry environment called once
  994. X */
  995. Xvoid
  996. XInitMonthEntries()
  997. X{
  998. X    if (MapStem == NULL)
  999. X        MakeMapStem();
  1000. X
  1001. X    if (access(MapStem, F_OK) < 0)
  1002. X        FoundCalendarDir = False;
  1003. X    else {
  1004. X        FoundCalendarDir = True;
  1005. X        /*
  1006. X         * If we can see the directory, then lurch into it
  1007. X         */
  1008. X        if (chdir(MapStem) < 0)
  1009. X            Fatal("Cannot change into %s", MapStem);
  1010. X    }
  1011. X}
  1012. X
  1013. X/*
  1014. X *    Find the base of the Calendar structure
  1015. X */
  1016. Xstatic void
  1017. XMakeMapStem()
  1018. X{    
  1019. X    char            buf[BUFSIZ];
  1020. X    struct passwd    *pw;
  1021. X
  1022. X    if (appResources.otheruser) {
  1023. X        /* someone else */
  1024. X        pw = getpwnam(appResources.otheruser);
  1025. X        if (pw == NULL)
  1026. X            Fatal("Cannot get password details for %s\n", appResources.otheruser);
  1027. X    } else {
  1028. X        pw = getpwuid(getuid());
  1029. X        if (pw == NULL)
  1030. X            Fatal("Cannot get password details for YOU!\n");
  1031. X    }
  1032. X    (void) sprintf(buf, "%s/%s", pw->pw_dir, appResources.directory);
  1033. X    MapStem = XtNewString(buf);
  1034. X}
  1035. X
  1036. X/*
  1037. X *    Get the entry for a specific month
  1038. X *
  1039. X *    xcalendar files are all
  1040. X *    xc<d><Mon><Year>
  1041. X *    or
  1042. X *    xc<dd><Mon><Year>
  1043. X *
  1044. X *    where d or dd is the day (%02d would have been better)
  1045. X *    <Mon> is a capitalised first three letters of the
  1046. X *        English month name. If you need compatibility
  1047. X *        don't redefine the short names in the resources
  1048. X *        for this program.
  1049. X *    <Year> is the full numeric year.
  1050. X *
  1051. X *    We will follow this BUT we will also make this program
  1052. X *    create subdirectories for new years
  1053. X *        xy<Year>
  1054. X *    to speed up file access
  1055. X */
  1056. XMonthEntry *
  1057. XGetMonthEntry(yr, mo)
  1058. X    Cardinal        yr;
  1059. X    Cardinal        mo;
  1060. X{
  1061. X    MeWrap         *mw;
  1062. X    char           *dir;
  1063. X    DIR            *dirp;
  1064. X    struct dirent  *dp;
  1065. X    int             da;
  1066. X    Boolean         inSubDir;
  1067. X    char            yearbuf[5];
  1068. X    char            monthbuf[4];
  1069. X
  1070. X    if ((mw = MeWrapSearch(yr, mo)) == NULL)
  1071. X        mw = NewMeWrap(yr, mo);
  1072. X    mw->mw_me.me_type = ME_MONTHLY;
  1073. X    if (!FoundCalendarDir)
  1074. X        return (&mw->mw_me);
  1075. X
  1076. X    /*
  1077. X     * need this for string match
  1078. X     */
  1079. X    (void) sprintf(yearbuf, "%d", yr);
  1080. X    (void) sprintf(monthbuf, "%s", appResources.smon[mo]);
  1081. X
  1082. X    /* we are in the directory */
  1083. X    /* so let's lookee here for the any files of interest */
  1084. X
  1085. X    dir = ".";
  1086. X    inSubDir = False;
  1087. X    if (mw->mw_dir) {
  1088. X        dir = mw->mw_dir;
  1089. X        inSubDir = True;
  1090. X    }
  1091. X    if ((dirp = opendir(dir)) == NULL)
  1092. X        Fatal("Cannot open directory: %s", MapStem);
  1093. X
  1094. X    for (da = 1; da < 32; da++)
  1095. X        if (mw->mw_have[da]) {
  1096. X            XtFree(mw->mw_have[da]);
  1097. X            mw->mw_have[da] = NULL;
  1098. X        }
  1099. X    while ((dp = readdir(dirp)) != NULL) {
  1100. X
  1101. X        switch (strlen(dp->d_name)) {
  1102. X
  1103. X        case 6:    /* xy<Year> ?? */
  1104. X            if (dp->d_name[0] == 'x' &&
  1105. X                dp->d_name[1] == 'y' &&
  1106. X                dp->d_name[2] == yearbuf[0] &&
  1107. X                dp->d_name[3] == yearbuf[1] &&
  1108. X                dp->d_name[4] == yearbuf[2] &&
  1109. X                dp->d_name[5] == yearbuf[3] &&
  1110. X                appResources.calCompat == False) {
  1111. X                /*
  1112. X                 * well - we're wasting
  1113. X                 * our time at the top
  1114. X                 * level - rejig things
  1115. X                     * to work in the
  1116. X                 * subdirectory
  1117. X                 */
  1118. X                inSubDir = True;
  1119. X                mw->mw_useTopDir = False;
  1120. X                mw->mw_dir = XtNewString(dp->d_name);
  1121. X                closedir(dirp);
  1122. X                if ((dirp = opendir(mw->mw_dir)) == NULL)
  1123. X                    Fatal("Cannot open directory %s/%s", MapStem, mw->mw_dir);
  1124. X
  1125. X            }
  1126. X            break;
  1127. X        case 10:    /* xc<d><Mon><Year> ?? */
  1128. X            if (dp->d_name[0] == 'x' &&
  1129. X                dp->d_name[1] == 'c' &&
  1130. X                isdigit(dp->d_name[2]) &&
  1131. X                dp->d_name[3] == monthbuf[0] &&
  1132. X                dp->d_name[4] == monthbuf[1] &&
  1133. X                dp->d_name[5] == monthbuf[2] &&
  1134. X                dp->d_name[6] == yearbuf[0] &&
  1135. X                dp->d_name[7] == yearbuf[1] &&
  1136. X                dp->d_name[8] == yearbuf[2] &&
  1137. X                dp->d_name[9] == yearbuf[3]) {
  1138. X                da = dp->d_name[2] - '0';
  1139. X                mw->mw_have[da] = ReadCalendarFile(mw->mw_dir, dp->d_name);
  1140. X                if (inSubDir == False)
  1141. X                    mw->mw_useTopDir = True;
  1142. X            }
  1143. X            break;
  1144. X        case 11:    /* xc<dd><Mon><Year> ?? */
  1145. X            if (dp->d_name[0] == 'x' &&
  1146. X                dp->d_name[1] == 'c' &&
  1147. X                isdigit(dp->d_name[2]) &&
  1148. X                isdigit(dp->d_name[3]) &&
  1149. X                dp->d_name[4] == monthbuf[0] &&
  1150. X                dp->d_name[5] == monthbuf[1] &&
  1151. X                dp->d_name[6] == monthbuf[2] &&
  1152. X                dp->d_name[7] == yearbuf[0] &&
  1153. X                dp->d_name[8] == yearbuf[1] &&
  1154. X                dp->d_name[9] == yearbuf[2] &&
  1155. X                dp->d_name[10] == yearbuf[3]) {
  1156. X                da = (dp->d_name[2] - '0') * 10 + (dp->d_name[3] - '0');
  1157. X                mw->mw_have[da] = ReadCalendarFile(mw->mw_dir, dp->d_name);
  1158. X                if (inSubDir == False)
  1159. X                    mw->mw_useTopDir = True;
  1160. X            }
  1161. X            break;
  1162. X        }
  1163. X    }
  1164. X    closedir(dirp);
  1165. X    return (&mw->mw_me);
  1166. X}
  1167. X
  1168. X/*
  1169. X *    Get the entry for the weekly strip
  1170. X *    Files are xw<Day> in the Calendar directory
  1171. X */
  1172. XMonthEntry *
  1173. XGetWeeklyEntry()
  1174. X{
  1175. X    MeWrap         *mw;
  1176. X    int             da;
  1177. X    DIR            *dirp;
  1178. X    struct dirent  *dp;
  1179. X
  1180. X    if ((mw = MeWrapSearch(0, 0)) == NULL)
  1181. X        mw = NewMeWrap(0, 0);
  1182. X    mw->mw_me.me_type = ME_WEEKLY;
  1183. X
  1184. X    if (!FoundCalendarDir)
  1185. X        return (&mw->mw_me);
  1186. X
  1187. X    if ((dirp = opendir(".")) == NULL)
  1188. X        Fatal("Cannot open directory: %s", MapStem);
  1189. X
  1190. X    for (da = 0; da < 7; da++)
  1191. X        if (mw->mw_have[da]) {
  1192. X            XtFree(mw->mw_have[da]);
  1193. X            mw->mw_have[da] = NULL;
  1194. X        }
  1195. X    while ((dp = readdir(dirp)) != NULL) {
  1196. X        if (dp->d_name[0] == 'x' &&
  1197. X            dp->d_name[1] == 'w' &&
  1198. X            ((da = DayMatch(&dp->d_name[2])) != -1)) {
  1199. X            mw->mw_have[da] = ReadCalendarFile(NULL, dp->d_name);
  1200. X        }
  1201. X    }
  1202. X    closedir(dirp);
  1203. X    return (&mw->mw_me);
  1204. X}
  1205. X
  1206. X/*
  1207. X * Look for a short name match with a day
  1208. X */
  1209. Xstatic int
  1210. XDayMatch(day)
  1211. X    String          day;
  1212. X{
  1213. X    register        i;
  1214. X
  1215. X    for (i = 0; i < 7; i++)
  1216. X        if (strcmp(day, appResources.sday[i]) == 0)
  1217. X            return (i);
  1218. X    return (-1);
  1219. X}
  1220. X
  1221. X/*
  1222. X * create a new MapWrap area
  1223. X */
  1224. Xstatic MeWrap  *
  1225. XNewMeWrap(yr, mo)
  1226. X    Cardinal        yr;
  1227. X    Cardinal        mo;
  1228. X{
  1229. X    register MeWrap *mw;
  1230. X    static MeWrap    zerow;
  1231. X    
  1232. X    mw = (MeWrap *) XtMalloc(sizeof(MeWrap));
  1233. X    *mw = zerow;
  1234. X    if (WrapEnd)
  1235. X        WrapEnd->mw_next = mw;
  1236. X    WrapEnd = mw;
  1237. X    if (WrapBase == NULL)
  1238. X        WrapBase = mw;
  1239. X    mw->mw_year = yr;
  1240. X    mw->mw_month = mo;
  1241. X    mw->mw_useTopDir = False;
  1242. X    return (mw);
  1243. X}
  1244. X
  1245. X/*
  1246. X * Search the MapWrap list for a year
  1247. X */
  1248. Xstatic MeWrap  *
  1249. XMeWrapSearch(yr, mo)
  1250. X    Cardinal        yr;
  1251. X    Cardinal        mo;
  1252. X{
  1253. X    register MeWrap *mw;
  1254. X
  1255. X    if (WrapBase)
  1256. X        for (mw = WrapBase; mw; mw = mw->mw_next)
  1257. X            if (yr == mw->mw_year && mo == mw->mw_month)
  1258. X                return (mw);
  1259. X    return (NULL);
  1260. X}
  1261. X
  1262. X/*
  1263. X * Register an instance of a month Return a pointer to an instance structure
  1264. X * so it can be filled in by the caller
  1265. X */
  1266. XInstance       *
  1267. XRegisterMonth(yr, mo, w)
  1268. X    Cardinal        yr;
  1269. X    Cardinal        mo;
  1270. X    Widget          w;
  1271. X{
  1272. X    register MeWrap *mw;
  1273. X    register Instance *ins;
  1274. X
  1275. X    if ((mw = MeWrapSearch(yr, mo)) == NULL)
  1276. X        mw = NewMeWrap(yr, mo);
  1277. X
  1278. X    ins = (Instance *) XtMalloc(sizeof(Instance));
  1279. X    ins->i_next = mw->mw_list;
  1280. X    mw->mw_list = ins;
  1281. X    ins->i_w = w;
  1282. X
  1283. X    callbacks[0].callback = DeRegisterMonth;
  1284. X#ifdef LONG_IS_32_BITS
  1285. X    callbacks[0].closure = (caddr_t) DatePack(0, 0, mo, yr);
  1286. X#else
  1287. X    callbacks[0].closure = (caddr_t) DatePack(mo, yr);
  1288. X#endif
  1289. X
  1290. X    XtAddCallbacks(w, XtNdestroyCallback, callbacks);
  1291. X    return (ins);
  1292. X}
  1293. X
  1294. X/*
  1295. X * Return the head of an instance list - given a date
  1296. X */
  1297. XInstance       *
  1298. XFindInstanceList(da)
  1299. X    Date           *da;
  1300. X{
  1301. X    register MeWrap *mw;
  1302. X
  1303. X    if ((mw = MeWrapSearch(da->year, da->month)) == NULL)
  1304. X        return (NULL);
  1305. X    return (mw->mw_list);
  1306. X}
  1307. X
  1308. X/*
  1309. X * Delete an instance
  1310. X */
  1311. X/* ARGSUSED */
  1312. Xstatic void
  1313. XDeRegisterMonth(w, closure, call_data)
  1314. X    Widget          w;
  1315. X    caddr_t         closure;
  1316. X    caddr_t         call_data;
  1317. X{
  1318. X    Cardinal        yr, mo;
  1319. X    register Instance *ins, *inlast;
  1320. X    register MeWrap *mw;
  1321. X
  1322. X    yr = YrUnpack((Cardinal) closure);
  1323. X    mo = MoUnpack((Cardinal) closure);
  1324. X
  1325. X    if ((mw = MeWrapSearch(yr, mo)) == NULL)
  1326. X        return;
  1327. X    for (ins = mw->mw_list, inlast = NULL;
  1328. X         ins;
  1329. X         inlast = ins, ins = ins->i_next) {
  1330. X        if (ins->i_w == w) {
  1331. X            if (inlast)
  1332. X                inlast->i_next = ins->i_next;
  1333. X            else
  1334. X                mw->mw_list = ins->i_next;
  1335. X            XtFree((char *) ins);
  1336. X            return;
  1337. X        }
  1338. X        inlast = ins;
  1339. X    }
  1340. X}
  1341. X
  1342. X
  1343. X/*
  1344. X * Read a calendar file into memory into a string
  1345. X * if the file is zero length then unlink and return NULL
  1346. X */
  1347. XString
  1348. XReadCalendarFile(dir, file)
  1349. X    String          dir;
  1350. X    String          file;
  1351. X{
  1352. X    char            fname[256];
  1353. X    int             fd;
  1354. X    String          destb;
  1355. X    struct stat     fsb;
  1356. X
  1357. X    if (dir) {
  1358. X        (void) sprintf(fname, "%s/%s", dir, file);
  1359. X        file = fname;
  1360. X    }
  1361. X    if ((fd = open(file, 0)) < 0) {
  1362. X        if (MyCalendar)
  1363. X            Fatal("Cannot open: %s for reading", file);
  1364. X        else
  1365. X            return(XtNewString(appResources.private));
  1366. X    }    
  1367. X    if (fstat(fd, &fsb) < 0)
  1368. X        Fatal("Cannot fstat %s", file);
  1369. X
  1370. X    if (fsb.st_size == 0) {
  1371. X        if (MyCalendar)
  1372. X            (void) unlink(file);
  1373. X        close(fd);
  1374. X        return (NULL);
  1375. X    }
  1376. X    destb = (String) XtMalloc(fsb.st_size + 1);
  1377. X
  1378. X    if (read(fd, (String) destb, fsb.st_size) != fsb.st_size)
  1379. X        Fatal("Read error on %s", file);
  1380. X
  1381. X    close(fd);
  1382. X
  1383. X    destb[fsb.st_size] = '\0';
  1384. X
  1385. X    return (destb);
  1386. X}
  1387. X
  1388. X/*
  1389. X * Check to see if we should create the top directory
  1390. X */
  1391. XBoolean
  1392. XNeedTop()
  1393. X{
  1394. X    if (!FoundCalendarDir) {
  1395. X        if (mkdir(MapStem, 0700) == -1) {
  1396. X            XBell(XtDisplay(toplevel), 0);
  1397. X            fprintf(stderr, "xcal: Could not create: %s directory.\n", MapStem);
  1398. X            perror("xcal: mkdir");
  1399. X            fflush(stderr);
  1400. X            return (False);
  1401. X        }
  1402. X        if (chdir(MapStem) < 0) {
  1403. X            XBell(XtDisplay(toplevel), 0);
  1404. X            fprintf(stderr, "xcal: Could not chdir into %s.\n", MapStem);
  1405. X            perror("xcal: chdir");
  1406. X            fflush(stderr);
  1407. X            return (False);
  1408. X        }
  1409. X        FoundCalendarDir = True;
  1410. X    }
  1411. X    return (True);
  1412. X}
  1413. X
  1414. X/*
  1415. X * Write a calendar file creating any directories which are needed
  1416. X * Return True if OK
  1417. X */
  1418. Xstatic Boolean
  1419. XWriteCalendarFile(mw, day, contents)
  1420. X    register MeWrap *mw;
  1421. X    Cardinal        day;
  1422. X    char           *contents;
  1423. X{
  1424. X    int             fd;
  1425. X    Cardinal        len;
  1426. X    char            fname[256];
  1427. X    char            cname[16];
  1428. X
  1429. X    len = strlen(contents);
  1430. X    if (len == 0) {
  1431. X        DeleteCalendarFile(mw, day);
  1432. X        return (True);
  1433. X    }
  1434. X    if (!NeedTop())
  1435. X        return (False);
  1436. X
  1437. X    /*
  1438. X     * So that looks OK 
  1439. X         * We can now create the output file. However, we
  1440. X     * would like to put any new data into subdirectories named for the
  1441. X     * year unless we are compatible with xcalendar
  1442. X     */
  1443. X    fname[0] = '\0';
  1444. X    if (appResources.calCompat == False && mw->mw_useTopDir == False) {
  1445. X        /*
  1446. X         * we have no data in the top directory
  1447. X         * so let's create the directory name
  1448. X         */
  1449. X        (void) sprintf(fname, "xy%d", mw->mw_year);
  1450. X
  1451. X        if (access(fname, F_OK) < 0) {
  1452. X            if (mkdir(fname, 0700) < 0) {
  1453. X                XBell(XtDisplay(toplevel), 0);
  1454. X                fprintf(stderr, "xcal: Could not create: %s/%s directory.\n", MapStem, fname);
  1455. X                perror("xcal: mkdir ");
  1456. X                fflush(stderr);
  1457. X                return (False);
  1458. X            }
  1459. X        }
  1460. X        strcat(fname, "/");
  1461. X    }
  1462. X    /*
  1463. X     * Whew - it looks as if we can now write the file
  1464. X     */
  1465. X    (void) sprintf(cname, "xc%d%s%d", day,
  1466. X               appResources.smon[mw->mw_month],
  1467. X               mw->mw_year);
  1468. X
  1469. X    strcat(fname, cname);
  1470. X
  1471. X    if ((fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
  1472. X        XBell(XtDisplay(toplevel), 0);
  1473. X        fprintf(stderr, "xcal: Could not open %s/%s for writing.\n", MapStem, fname);
  1474. X        perror("xcal: open");
  1475. X        fflush(stderr);
  1476. X        return (False);
  1477. X    }
  1478. X    if (write(fd, contents, len) != len) {
  1479. X        XBell(XtDisplay(toplevel), 0);
  1480. X        fprintf(stderr, "xcal: Write error %s/%s file.\n", MapStem, fname);
  1481. X        perror("xcal: write");
  1482. X        fflush(stderr);
  1483. X        close(fd);
  1484. X        return (False);
  1485. X    }
  1486. X    close(fd);
  1487. X    /*
  1488. X     * tickle the alarm system if we have altered `today'
  1489. X     */
  1490. X    if (today.day == day && today.month == mw->mw_month &&
  1491. X        today.year == mw->mw_year)
  1492. X        AlarmFilePoll(NULL);
  1493. X    return (True);
  1494. X}
  1495. X
  1496. Xstatic void
  1497. XDeleteCalendarFile(mw, day)
  1498. X    register MeWrap *mw;
  1499. X    Cardinal        day;
  1500. X{
  1501. X    char            fname[256];
  1502. X    char            cname[16];
  1503. X
  1504. X    fname[0] = '\0';
  1505. X
  1506. X    if (mw->mw_useTopDir == False) {
  1507. X        /*
  1508. X         * we have no data in the top directory 
  1509. X         * so let's create the directory name
  1510. X         */
  1511. X        (void) sprintf(fname, "xy%d", mw->mw_year);
  1512. X
  1513. X        if (access(fname, F_OK) < 0)
  1514. X            return;
  1515. X        strcat(fname, "/");
  1516. X    }
  1517. X    (void) sprintf(cname, "xc%d%s%d", day,
  1518. X               appResources.smon[mw->mw_month],
  1519. X               mw->mw_year);
  1520. X
  1521. X    strcat(fname, cname);
  1522. X
  1523. X    unlink(fname);
  1524. X
  1525. X    /*
  1526. X     * tickle the alarm system if we have altered `today'
  1527. X     */
  1528. X    if (today.day == day && today.month == mw->mw_month &&
  1529. X        today.year == mw->mw_year)
  1530. X        AlarmFilePoll(NULL);
  1531. X}
  1532. X
  1533. X/*
  1534. X * Write daily file out
  1535. X */
  1536. Xstatic          Boolean
  1537. XWriteWeeklyFile(mw, day, contents)
  1538. X    register MeWrap *mw;
  1539. X    Cardinal        day;
  1540. X    char           *contents;
  1541. X{
  1542. X    int             fd;
  1543. X    Cardinal        len;
  1544. X    char           *fname;
  1545. X
  1546. X    fname = MakeWeeklyName(day);
  1547. X
  1548. X    len = strlen(contents);
  1549. X    if (len == 0)
  1550. X        (void) unlink(fname);
  1551. X    else {
  1552. X        if ((fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
  1553. X            XBell(XtDisplay(toplevel), 0);
  1554. X            fprintf(stderr, "xcal: Could not open %s/%s for writing.\n", MapStem, fname);
  1555. X            perror("xcal: open");
  1556. X            fflush(stderr);
  1557. X            return (False);
  1558. X        }
  1559. X        if (write(fd, contents, len) != len) {
  1560. X            XBell(XtDisplay(toplevel), 0);
  1561. X            fprintf(stderr, "xcal: Write error %s/%s file.\n", MapStem, fname);
  1562. X            perror("xcal: write");
  1563. X            fflush(stderr);
  1564. X            close(fd);
  1565. X            return (False);
  1566. X        }
  1567. X        close(fd);
  1568. X    }
  1569. X    /*
  1570. X     * tickle the alarm system if we have altered `today'
  1571. X     */
  1572. X    if (today.wday == day)
  1573. X        AlarmFilePoll(NULL);
  1574. X
  1575. X    return (True);
  1576. X}
  1577. X
  1578. X/*
  1579. X * Create a standard weekly file name
  1580. X */
  1581. XString
  1582. XMakeWeeklyName(day)
  1583. X    Cardinal        day;
  1584. X{
  1585. X    static char     fname[16];
  1586. X
  1587. X    (void) sprintf(fname, "xw%s", appResources.sday[day]);
  1588. X    return (fname);
  1589. X}
  1590. X
  1591. X/*
  1592. X * Get the contents of the current Weekly file if any
  1593. X */
  1594. XString
  1595. XGetWeeklyFile(day)
  1596. X    Cardinal        day;
  1597. X{
  1598. X    char           *fname;
  1599. X
  1600. X    if (FoundCalendarDir == False)
  1601. X        return (NULL);
  1602. X
  1603. X    fname = MakeWeeklyName(day);
  1604. X
  1605. X    if (access(fname, F_OK) < 0)
  1606. X        return (NULL);
  1607. X
  1608. X    return (ReadCalendarFile(NULL, fname));
  1609. X}
  1610. X
  1611. X/*
  1612. X * Start up an editor window from the callback
  1613. X * Pass the calling widget so we can change its contents after the edit
  1614. X */
  1615. X/* ARGSUSED */
  1616. Xvoid
  1617. XStartEditing(w, da, but)
  1618. X    Widget          w;
  1619. X    Date           *da;
  1620. X    Widget        but;
  1621. X{
  1622. X    register MeWrap *mw;
  1623. X    register EditLine *ed;
  1624. X    static EditLine    zeroe;
  1625. X    
  1626. X    if ((mw = MeWrapSearch(da->year, da->month)) == NULL)
  1627. X        mw = NewMeWrap(da->year, da->month);    /* shouldn`t happen */
  1628. X    /*
  1629. X     * see if we are editing this day
  1630. X     */
  1631. X    if (EditCheck(w, mw, da))
  1632. X        return;
  1633. X    /*
  1634. X     * Things are looking OK
  1635. X     * Create a new editing record
  1636. X     */
  1637. X    ed = (EditLine *) XtMalloc(sizeof(EditLine));
  1638. X    *ed = zeroe;
  1639. X    ed->ed_day = da->day;
  1640. X    ed->ed_meWrap = mw;    /* help for unlinking */
  1641. X    /*
  1642. X     * Do we have a string now
  1643. X     */
  1644. X    if (mw->mw_have[da->day]) {
  1645. X        ed->ed_size = appResources.textbufsz + strlen(mw->mw_have[da->day]) + 1;
  1646. X        ed->ed_data = XtMalloc(ed->ed_size);
  1647. X        strcpy(ed->ed_data, mw->mw_have[da->day]);
  1648. X    } else {
  1649. X        ed->ed_data = XtMalloc(ed->ed_size = appResources.textbufsz);
  1650. X        *ed->ed_data = '\0';
  1651. X    }
  1652. X    /*
  1653. X     * put the record into the list
  1654. X     */
  1655. X    ed->ed_next = mw->mw_ed;
  1656. X    mw->mw_ed = ed;
  1657. X    /*
  1658. X     * We fiddle with the source widget too 
  1659. X     * Desensitise visible source widgets
  1660. X     * If the user starts up another strip for this month then
  1661. X     * the NoEditIsPossible() code above copes
  1662. X     */
  1663. X    SetAllButtons(mw->mw_list, da->day, False);
  1664. X    /*
  1665. X     * Now we should start up the edit window for this month
  1666. X     */
  1667. X    StartDayEditor(mw, da, but);
  1668. X}
  1669. X
  1670. X/*
  1671. X *    See if we are editing a day already
  1672. X *    complain and return 1 if we are
  1673. X *    return 0 if not
  1674. X */
  1675. Xstatic int
  1676. XEditCheck(w, mw, da)
  1677. X    Widget        w;
  1678. X    MeWrap        *mw;
  1679. X    Date        *da;
  1680. X{
  1681. X    register EditLine *ed;
  1682. X
  1683. X    /*
  1684. X     * see if we are already editing this day
  1685. X     */
  1686. X    for (ed = mw->mw_ed; ed; ed = ed->ed_next) {
  1687. X        if (ed->ed_day == da->day) {    /* we are! */
  1688. X            /* Complain via a popup */
  1689. X            switch (StripType(mw)) {
  1690. X            case ME_MONTHLY:
  1691. X                NoEditIsPossible(w, da);
  1692. X                break;
  1693. X            case ME_WEEKLY:
  1694. X                NoDayEditIsPossible(w, da);
  1695. X                break;
  1696. X            }
  1697. X            return 1;
  1698. X        }
  1699. X    }
  1700. X    return 0;
  1701. X}
  1702. X
  1703. X/*
  1704. X * Set all the relevant buttons in a widget list to off or on
  1705. X */
  1706. Xstatic void
  1707. XSetAllButtons(ins, day, val)
  1708. X    Instance       *ins;
  1709. X    Cardinal        day;
  1710. X    Boolean         val;
  1711. X{
  1712. X    for (; ins; ins = ins->i_next)
  1713. X        XtSetSensitive(ins->i_day_info[day], val);
  1714. X}
  1715. X
  1716. X/*
  1717. X * Start up a day editor Modelled on xcalendar.c
  1718. X */
  1719. Xvoid
  1720. XStartDayEditor(mw, da, but)
  1721. X    register MeWrap *mw;
  1722. X    register Date  *da;
  1723. X    Widget but;
  1724. X{
  1725. X    register EditLine *ed = mw->mw_ed;    /* top of the list is ours */
  1726. X    Widget          lw, et;
  1727. X    Widget          frame;
  1728. X    Arg             args[10];
  1729. X    Cardinal        nargs;
  1730. X    char            buf[BUFSIZ];
  1731. X    void            EditHelp();
  1732. X    
  1733. X    ed->ed_popup = XtCreatePopupShell("edit", topLevelShellWidgetClass, toplevel, NULL, 0);
  1734. X
  1735. X    if (but && XtIsSubclass(but, commandWidgetClass))
  1736. X        ButtonOff(but, ed->ed_popup);
  1737. X
  1738. X    /*
  1739. X     * Create the title line - which is a form containing buttons and a
  1740. X     * date label
  1741. X     */
  1742. X    et = XtCreateManagedWidget("panel", panedWidgetClass, ed->ed_popup, NULL, 0);
  1743. X
  1744. X    nargs = 0;
  1745. X    argLD(XtNshowGrip, False);
  1746. X    argLD(XtNskipAdjust, True);
  1747. X    argLD(XtNdefaultDistance, 1);
  1748. X    frame = XtCreateManagedWidget("title", formWidgetClass, et, args, nargs);
  1749. X    /*
  1750. X     * Take label "quit" from resources
  1751. X     */
  1752. X    callbacks[0].callback = FinishEditing;
  1753. X    callbacks[0].closure = (caddr_t) ed;
  1754. X    nargs = 0;
  1755. X    argLD(XtNcallback, callbacks);
  1756. X    argLD(XtNfromHoriz, NULL);
  1757. X    argLD(XtNleft, XtChainLeft);
  1758. X    argLD(XtNright, XtChainLeft);
  1759. X    lw = ed->ed_quit = XtCreateManagedWidget("quit", commandWidgetClass, frame, args, nargs);
  1760. X
  1761. X    /*
  1762. X     * Take label "save" from resources
  1763. X     */
  1764. X    if (MyCalendar) {
  1765. X        callbacks[0].callback = SaveEdits;
  1766. X        callbacks[0].closure = (caddr_t) ed;
  1767. X        nargs = 0;
  1768. X        argLD(XtNcallback, callbacks);
  1769. X        argLD(XtNfromHoriz, ed->ed_quit);
  1770. X        argLD(XtNleft, XtChainLeft);
  1771. X        argLD(XtNright, XtChainLeft);
  1772. X        argLD(XtNsensitive, False);
  1773. X        lw = ed->ed_save = XtCreateManagedWidget("save", commandWidgetClass, frame, args, nargs);
  1774. X        
  1775. X    }    
  1776. X    if (appResources.giveHelp) {
  1777. X        /*
  1778. X         * Take label "help" from resources
  1779. X         */
  1780. X        callbacks[0].callback = EditHelp;
  1781. X        callbacks[0].closure = (caddr_t) 0;
  1782. X        nargs = 0;
  1783. X        argLD(XtNcallback, callbacks);
  1784. X        argLD(XtNfromHoriz, lw);
  1785. X        argLD(XtNleft, XtChainLeft);
  1786. X        argLD(XtNright, XtChainLeft);
  1787. X        lw = XtCreateManagedWidget("help", commandWidgetClass, frame, args, nargs);
  1788. X    }
  1789. X    switch (StripType(mw)) {
  1790. X    case ME_MONTHLY:
  1791. X        FmtDate(da, buf, sizeof buf, appResources.editfmt);
  1792. X        break;
  1793. X    case ME_WEEKLY:
  1794. X        (void) strcpy(buf, appResources.day[da->day]);
  1795. X        break;
  1796. X    }
  1797. X    nargs = 0;
  1798. X    argLD(XtNlabel, buf);
  1799. X    argLD(XtNborderWidth, 0);
  1800. X    argLD(XtNfromHoriz, lw);
  1801. X    argLD(XtNfromVert, NULL);
  1802. X    argLD(XtNvertDistance, 2);
  1803. X    argLD(XtNleft, XtChainLeft);
  1804. X    argLD(XtNright, XtChainRight);
  1805. X    lw = XtCreateManagedWidget("date", labelWidgetClass, frame, args, nargs);
  1806. X
  1807. X    /*
  1808. X     * The text widget is in the pane below
  1809. X     * The Scroll Attributes are controlled from the application
  1810. X     * defaults file
  1811. X     */
  1812. X    callbacks[0].callback = TextChanged;
  1813. X    callbacks[0].closure = (caddr_t) ed;
  1814. X    nargs = 0;
  1815. X    argLD(XtNshowGrip, False);
  1816. X    argLD(XtNstring, ed->ed_data);
  1817. X    argLD(XtNeditType, XawtextEdit);
  1818. X    argLD(XtNlength, ed->ed_size);
  1819. X    argLD(XtNuseStringInPlace, True);
  1820. X    argLD(XtNcallback, callbacks);
  1821. X    ed->ed_text = XtCreateManagedWidget("text", asciiTextWidgetClass, et, args, nargs);
  1822. X
  1823. X    XtPopup(ed->ed_popup, XtGrabNone);
  1824. X
  1825. X}
  1826. X
  1827. X/*
  1828. X * Callback for text widget
  1829. X * This gets called before the string is updated
  1830. X */
  1831. X/* ARGSUSED */
  1832. Xstatic void
  1833. XTextChanged(w, closure, call_data)
  1834. X    Widget          w;
  1835. X    caddr_t         closure;
  1836. X    caddr_t         call_data;
  1837. X{
  1838. X    register EditLine *ed = (EditLine *) closure;
  1839. X
  1840. X    if (MyCalendar)
  1841. X        XtSetSensitive(ed->ed_save, True);
  1842. X}
  1843. X
  1844. X
  1845. X/* ARGSUSED */
  1846. Xstatic void
  1847. XSaveEdits(w, closure, call_data)
  1848. X    Widget          w;
  1849. X    caddr_t         closure;
  1850. X    caddr_t         call_data;
  1851. X{
  1852. X    register EditLine *ed = (EditLine *) closure;
  1853. X    register MeWrap *mw;
  1854. X    register Cardinal day;
  1855. X
  1856. X    mw = ed->ed_meWrap;
  1857. X    day = ed->ed_day;
  1858. X
  1859. X    switch (StripType(mw)) {
  1860. X    case ME_MONTHLY:
  1861. X        if (WriteCalendarFile(mw, day, ed->ed_data) == False)
  1862. X            return;
  1863. X        break;
  1864. X    case ME_WEEKLY:
  1865. X        if (WriteWeeklyFile(mw, day, ed->ed_data) == False)
  1866. X            return;
  1867. X        break;
  1868. X    }
  1869. X    /*
  1870. X     * Otherwise change the displayed string
  1871. X     */
  1872. X    if (mw->mw_have[day])
  1873. X        XtFree(mw->mw_have[day]);
  1874. X    mw->mw_have[day] = XtMalloc(strlen(ed->ed_data) + 1);
  1875. X    strcpy(mw->mw_have[day], ed->ed_data);
  1876. X    /*
  1877. X     * Update the visual image
  1878. X     */
  1879. X    UpdateDayDetails(mw, day);
  1880. X    XtSetSensitive(ed->ed_save, False);
  1881. X}
  1882. X
  1883. Xstatic void
  1884. XUpdateDayDetails(mw, day)
  1885. X    MeWrap        *mw;
  1886. X    Cardinal    day;
  1887. X{
  1888. X    Instance    *ins;
  1889. X    int        nargs;
  1890. X    Arg             args[3];
  1891. X
  1892. X    XtSetArg(args[0], XtNlabel, mw->mw_have[day]);
  1893. X    for (ins = mw->mw_list; ins; ins = ins->i_next) {
  1894. X        nargs = 1;
  1895. X        if (*mw->mw_have[day] == '\0') {
  1896. X            argLD(XtNforeground, ins->i_col.fg);
  1897. X            argLD(XtNbackground, ins->i_col.bg);
  1898. X        }
  1899. X        XtSetValues(ins->i_day_info[day], args, nargs);
  1900. X    }
  1901. X
  1902. X    /*
  1903. X     * worry about updating the memo system
  1904. X     */
  1905. X
  1906. X    switch (StripType(mw)) {
  1907. X    case ME_MONTHLY:
  1908. X        if (today.day == day && today.month == mw->mw_month &&
  1909. X            today.year == mw->mw_year)
  1910. X            UpdateMemo();
  1911. X        break;
  1912. X    case ME_WEEKLY:
  1913. X        if (today.wday == day)
  1914. X            UpdateMemo();
  1915. X        break;
  1916. X    }
  1917. X
  1918. X}
  1919. X
  1920. Xstatic void
  1921. XFinishEditing(w, closure, call_data)
  1922. X    Widget          w;
  1923. X    caddr_t         closure;
  1924. X    caddr_t         call_data;
  1925. X{
  1926. X    register EditLine *ed = (EditLine *) closure;
  1927. X    register MeWrap *mw;
  1928. X    Cardinal        day;
  1929. X
  1930. X    XtSetSensitive(ed->ed_quit, False);
  1931. X    if (MyCalendar)
  1932. X        XtSetSensitive(ed->ed_save, False);
  1933. X    mw = ed->ed_meWrap;
  1934. X    day = ed->ed_day;
  1935. X
  1936. X    if (mw->mw_have[day] == NULL) {
  1937. X        if (*ed->ed_data) {
  1938. X            CheckExit(ed);
  1939. X            return;
  1940. X        }
  1941. X    } else if (strcmp(mw->mw_have[day], ed->ed_data)) {
  1942. X        CheckExit(ed);
  1943. X        return;
  1944. X    }
  1945. X    CleanEditPanel(w, ed, call_data);
  1946. X}
  1947. X
  1948. Xstatic void
  1949. XCleanEditPanel(w, closure, call_data)
  1950. X    Widget          w;
  1951. X    caddr_t         closure;
  1952. X    caddr_t         call_data;
  1953. X{
  1954. X    register EditLine *ed = (EditLine *) closure;
  1955. X    register EditLine *edl, *eds;
  1956. X    register MeWrap *mw;
  1957. X    Cardinal        day;
  1958. X    Widget          popup;
  1959. X
  1960. X    mw = ed->ed_meWrap;
  1961. X    day = ed->ed_day;
  1962. X    popup = ed->ed_popup;
  1963. X
  1964. X    XtFree(ed->ed_data);
  1965. X
  1966. X    for (edl = NULL, eds = mw->mw_ed;
  1967. X         eds;
  1968. X         edl = eds, eds = eds->ed_next) {
  1969. X        if (eds == ed) {
  1970. X            if (edl)
  1971. X                edl->ed_next = ed->ed_next;
  1972. X            else
  1973. X                mw->mw_ed = ed->ed_next;
  1974. X            break;
  1975. X        }
  1976. X    }
  1977. X    XtFree((char *) ed);
  1978. X    XtPopdown(popup);
  1979. X    XtDestroyWidget(popup);
  1980. X
  1981. X    SetAllButtons(mw->mw_list, day, True);
  1982. X}
  1983. X
  1984. X/*
  1985. X * We are trying to leave with saving the data
  1986. X * let us see if the user really wants to
  1987. X */
  1988. Xstatic void
  1989. XCheckExit(ed)
  1990. X    register EditLine *ed;
  1991. X{
  1992. X
  1993. X    DialogPopup(ed->ed_quit, CheckDia, ed, NULL);
  1994. X}
  1995. X
  1996. X/*
  1997. X * Here we do the work
  1998. X */
  1999. Xstatic void
  2000. XCheckDia(pop, ed)
  2001. X    Widget          pop;
  2002. X    EditLine       *ed;
  2003. X{
  2004. X    Widget          dia;
  2005. X
  2006. X    XtSetSensitive(ed->ed_quit, False);
  2007. X    /* Take "Save file?" from resources */
  2008. X    dia = XtCreateManagedWidget("check", dialogWidgetClass, pop, NULL, 0);
  2009. X    XawDialogAddButton(dia, "yes", YesCheck, ed);
  2010. X    XawDialogAddButton(dia, "no", NoCheck, ed);
  2011. X}
  2012. X
  2013. X/* ARGSUSED */
  2014. Xstatic void
  2015. XYesCheck(w, closure, call_data)
  2016. X    Widget          w;
  2017. X    caddr_t         closure;
  2018. X    caddr_t         call_data;
  2019. X{
  2020. X    SaveEdits(w, closure, call_data);
  2021. X    CleanEditPanel(w, closure, call_data);
  2022. X    XtDestroyWidget(XtParent(XtParent(w)));
  2023. X
  2024. X}
  2025. X
  2026. X/* ARGSUSED */
  2027. Xstatic void
  2028. XNoCheck(w, closure, call_data)
  2029. X    Widget          w;
  2030. X    caddr_t         closure;
  2031. X    caddr_t         call_data;
  2032. X{
  2033. X    CleanEditPanel(w, closure, call_data);
  2034. X    XtDestroyWidget(XtParent(XtParent(w)));
  2035. X}
  2036. X
  2037. X
  2038. X/*
  2039. X * Slighty formatted XtError
  2040. X */
  2041. X/* VARARGS1 */
  2042. Xvoid
  2043. XFatal(fmt, a, b)
  2044. X    char           *fmt;
  2045. X    char           *a;
  2046. X    char           *b;
  2047. X{
  2048. X    char            buf[BUFSIZ];
  2049. X
  2050. X    (void) sprintf(buf, fmt, a, b);
  2051. X    XtAppError(appContext, buf);
  2052. X    /* NOTREACHED */
  2053. X}
  2054. X
  2055. X/*
  2056. X * These routines used to insert text into a file
  2057. X * from the middle button press.
  2058. X * Code called from xcal_strip.c
  2059. X * The routine is responsible for freeing the text string
  2060. X */
  2061. Xvoid
  2062. XAppendText(w, da, txt)
  2063. X    Widget        w;
  2064. X    Date        *da;
  2065. X    String        txt;
  2066. X{
  2067. X    MeWrap        *mw;
  2068. X    Cardinal    len;
  2069. X    Cardinal    srclen;
  2070. X    String        newstr;
  2071. X
  2072. X    if ((mw = MeWrapSearch(da->year, da->month)) == NULL)
  2073. X        mw = NewMeWrap();    /* shouldn`t happen */
  2074. X
  2075. X    if (EditCheck(w, mw, da))
  2076. X        return;
  2077. X
  2078. X    /*
  2079. X     * if we have some text already, we must append the new text to it
  2080. X     */
  2081. X    if (mw->mw_have[da->day]) {
  2082. X        /*
  2083. X         * size of new string is sum of previous two
  2084. X         * plus two for the nulls at the end of the string
  2085. X         * plus one because we made need to insert a newline
  2086. X         * after the old text
  2087. X         */
  2088. X        srclen = strlen(mw->mw_have[da->day]);
  2089. X        if (srclen) {
  2090. X            len = srclen + strlen(txt) +3;
  2091. X            newstr = XtMalloc(len);
  2092. X            strcpy(newstr, mw->mw_have[da->day]);
  2093. X            if (newstr[srclen] == '\0') {
  2094. X                newstr[srclen++] = '\n';
  2095. X                newstr[srclen] = '\0';
  2096. X            }
  2097. X            strcat(newstr, txt);
  2098. X            XtFree(txt);
  2099. X            txt = newstr;
  2100. X        }
  2101. X    }
  2102. X
  2103. X    switch (StripType(mw)) {
  2104. X    case ME_MONTHLY:
  2105. X        if (WriteCalendarFile(mw, da->day, txt) == False)
  2106. X            return;
  2107. X        break;
  2108. X    case ME_WEEKLY:
  2109. X        if (WriteWeeklyFile(mw, da->day, txt) == False)
  2110. X            return;
  2111. X        break;
  2112. X    }
  2113. X    /*
  2114. X     * Otherwise change the displayed string
  2115. X     */
  2116. X    if (mw->mw_have[da->day])
  2117. X        XtFree(mw->mw_have[da->day]);
  2118. X    mw->mw_have[da->day] = txt;
  2119. X
  2120. X    UpdateDayDetails(mw, da->day);
  2121. X}
  2122. END_OF_FILE
  2123. if test 27722 -ne `wc -c <'xcal_edit.c'`; then
  2124.     echo shar: \"'xcal_edit.c'\" unpacked with wrong size!
  2125. fi
  2126. # end of 'xcal_edit.c'
  2127. fi
  2128. echo shar: End of archive 8 \(of 8\).
  2129. cp /dev/null ark8isdone
  2130. MISSING=""
  2131. for I in 1 2 3 4 5 6 7 8 ; do
  2132.     if test ! -f ark${I}isdone ; then
  2133.     MISSING="${MISSING} ${I}"
  2134.     fi
  2135. done
  2136. if test "${MISSING}" = "" ; then
  2137.     echo You have unpacked all 8 archives.
  2138.     rm -f ark[1-9]isdone
  2139. else
  2140.     echo You still need to unpack the following archives:
  2141.     echo "        " ${MISSING}
  2142. fi
  2143. ##  End of shell archive.
  2144. exit 0
  2145.  
  2146. exit 0 # Just in case...
  2147. -- 
  2148.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  2149. \X/  Amiga: The only way to fly!  |    sources-x@sterling.com
  2150.        "It's intuitively obvious to the most casual observer..."
  2151.  GCS d++(--) -p+ c++ !l u++ e+ m+(-) s++/++ n h--- f+ g+++ w+ t++ r+ y+
  2152.