revert between 56095 -> 55830 in arch
[AROS.git] / workbench / tools / Edit / Prefs.c
blobaffdd0adbfd8fedc01224230f14bb0c2b3c79214
1 /***************************************************************
2 **** prefs.c: Preference file and Inter-Process Communica- ****
3 **** tion with JanoPrefs. © T.Pierron, C.Guillaume ****
4 **** Free software under GNU license, started on 16/4/2000 ****
5 ***************************************************************/
7 #define ASL_V38_NAMES_ONLY
8 #include <intuition/intuition.h>
9 #include <intuition/screens.h>
10 #include <intuition/intuitionbase.h>
11 #include <libraries/asl.h>
12 #include <libraries/iffparse.h>
13 #include <graphics/gfxbase.h>
14 #include <graphics/modeid.h>
15 #include <dos/dos.h>
16 #include <dos/dostags.h>
17 #include <stddef.h> /* offsetof() */
18 #include "Jed.h"
19 #include "IPC_Prefs.h"
20 #include "Utility.h"
21 #include "Events.h"
22 #include "ProtoTypes.h"
24 #define CATCOMP_NUMBERS
25 #ifndef JANOPREF
26 #include "strings.h"
27 #else
28 #include "Utils.h"
29 #include "../../tools/Edit/strings.h"
30 #endif
31 extern struct IntuitionBase *IntuitionBase;
32 extern struct GfxBase * GfxBase;
33 extern struct Library * AslBase;
34 extern struct Library * IFFParseBase;
36 PREFS prefs, tmpprefs;
37 UBYTE File[] = APPNAME ".prefs";
38 UBYTE ENV[] = "ENVARC:";
39 UBYTE Path[100];
41 /** Special table for word separation **/
42 UBYTE WordsSep[MAX_SPLIT] = "!-/:-?[-]^`{-¿×÷";
43 UBYTE SpaceType[] = "\t\n\r \177";
44 UBYTE TypeChar[256];
46 /** Default pens number **/
47 struct pens DefaultPens = {
48 BACKGROUNDPEN, TEXTPEN, FILLPEN, HIGHLIGHTTEXTPEN, SHINEPEN, TEXTPEN,
49 SHINEPEN, SHADOWPEN, BACKGROUNDPEN, TEXTPEN, -4, BACKGROUNDPEN
52 /** Which part of editor to modify according to color changes **/
53 UBYTE Modif[] = {
54 EDIT_AREA, EDIT_AREA, EDIT_AREA, EDIT_AREA, 0, 0, EDIT_GUI, EDIT_GUI,
55 EDIT_GUI, EDIT_GUI, EDIT_GUI, EDIT_GUI
58 /** Little wrapper **/
59 #define OFFS(x) (UBYTE)(offsetof(PREFS,x))
61 /** Offset of structure PREFS **/
62 UBYTE offsets[] = {
63 OFFS(use_pub), OFFS(wordssep), OFFS(attrtxt), OFFS(attrtxt.ta_YSize),
64 OFFS(attrscr), OFFS(attrscr.ta_YSize), OFFS(left), OFFS(scrw),
65 OFFS(scrd), OFFS(modeid), OFFS(vmd), OFFS(pen)
67 /** And correspond size (0=null-terminated string) **/
68 UBYTE sizefields[] = {
69 12*sizeof(char), 0, 0, sizeof(prefs.attrtxt)-sizeof(STRPTR), 0,
70 sizeof(prefs.attrscr)-sizeof(STRPTR), 4*sizeof(prefs.left), sizeof(prefs.scrw),
71 sizeof(prefs.scrd), sizeof(prefs.modeid), sizeof(prefs.vmd), sizeof(prefs.pen)
74 UBYTE FontName[60];
76 /*** Convert a TextFont struct into a TextAttr ***/
77 void text_to_attr(struct TextFont *src, struct TextAttr *dest)
79 dest->ta_Name = src->tf_Message.mn_Node.ln_Name;
80 dest->ta_YSize = src->tf_YSize;
81 dest->ta_Style = FS_NORMAL;
82 dest->ta_Flags = src->tf_Flags;
85 /*** Extract some information from a Screen structure ***/
86 void info_screen(PREFS *prefs, struct Screen *Scr)
88 prefs->parent = Scr;
89 prefs->scrw = Scr->Width;
90 prefs->scrh = Scr->Height;
91 prefs->vmd = GetVPModeID( &Scr->ViewPort );
92 prefs->scrd = Scr->RastPort.BitMap->Depth;
95 /*** Unpack separators description string ***/
96 void unpack_separators(UBYTE *Fmt)
98 UBYTE *src,a,b;
99 memset(TypeChar,ALPHA,sizeof(TypeChar));
100 for(src=Fmt; *src; src++)
102 /* Avoid special character meaning */
103 if(*src == '\\' && src[1]) src++;
104 TypeChar[*src] = SEPARATOR;
105 /* Range of char specifier? */
106 if(src[1] == '-' && *src<src[2])
107 for(a=*src,b=src[2]; a<=b; a++)
108 TypeChar[a] = SEPARATOR;
110 /* Force space char type */
111 for(src=SpaceType; *src; src++)
112 TypeChar[*src] = SPACE;
115 /*** Set preference to default settings ***/
116 void set_default_prefs( PREFS *prefs, struct Screen *def )
118 memset(prefs, 0, sizeof(*prefs));
119 CopyMem(&DefaultPens, &prefs->pen, sizeof(prefs->pen));
120 prefs->auto_indent = 1;
121 prefs->matchcase = 0;
122 prefs->tabsize = 8;
123 prefs->scrfont = def->RastPort.Font;
124 prefs->txtfont = GfxBase->DefaultFont;
125 prefs->width = prefs->txtfont->tf_XSize * 80;
126 prefs->top = def->BarHeight + 1;
127 prefs->height = def->Height - prefs->top;
128 prefs->modeid = PAL_MONITOR_ID | HIRES_KEY;
130 /* Convert dynamic struct to static one */
131 text_to_attr(prefs->scrfont, &prefs->attrscr);
132 text_to_attr(prefs->txtfont, &prefs->attrtxt);
133 unpack_separators(prefs->wordssep = WordsSep);
134 info_screen(prefs, def);
135 init_tabstop(8);
138 /* Open preference file according to `mode' */
139 APTR open_prefs(STRPTR file, UBYTE mode)
141 struct IFFHandle * pref;
143 if( IFFParseBase != NULL && (pref = (APTR) AllocIFF() ) )
145 BPTR fh = 0;
146 switch( mode )
148 case MODE_USE:
149 if(file == NULL)
151 /* First: search in local directory */
152 CopyMem(File, Path, sizeof(File)-1);
153 if(BNULL == (fh = Open( Path, MODE_OLDFILE )))
155 /* Otherwise, look in directory ENVARC */
156 CopyMem(ENV, Path,sizeof(ENV)-1);
157 CopyMem(File,Path+sizeof(ENV)-1,sizeof(File)-1);
158 fh = Open( Path, MODE_OLDFILE );
160 } else if(BNULL != (fh = Open( file, MODE_OLDFILE )))
161 strcpy(Path, file);
162 break;
163 case MODE_SAVE:
164 fh = Open(Path, MODE_NEWFILE);
166 /* Did we have a opened file? */
167 if( fh )
169 pref->iff_Stream = (IPTR) fh;
170 /* Use DOS function for accessing it */
171 InitIFFasDOS( pref );
172 /* Open it through iffparse */
173 if( !OpenIFF( pref, mode == MODE_SAVE ? IFFF_WRITE : IFFF_READ) )
174 return pref;
176 FreeIFF( pref );
178 return NULL;
181 /*** Close properly IFF handle ***/
182 void close_prefs( struct IFFHandle * file )
184 CloseIFF( file );
185 if( file->iff_Stream ) Close((BPTR) file->iff_Stream );
186 FreeIFF( file );
189 /*** Try to load a preference file ***/
190 UBYTE load_prefs(PREFS *prefs, STRPTR filename)
192 APTR file;
193 UBYTE err = RETURN_OK;
195 /* Locate preference file */
196 if( (file = open_prefs(filename, MODE_USE)) )
198 /* Search for PREF/JANO chunk in this file */
199 if( !StopChunk(file, ID_PREF, ID_JANO) )
201 if( !ParseIFF(file, IFFPARSE_SCAN) )
203 struct ContextNode * cn = CurrentChunk(file);
204 STRPTR buffer = NULL;
205 UWORD ByteRead = 0;
207 if( cn->cn_Type == ID_PREF && cn->cn_ID == ID_JANO &&
208 (buffer = (STRPTR) AllocVec(cn->cn_Size, MEMF_PUBLIC)) &&
209 ReadChunkBytes(file, buffer, cn->cn_Size) == cn->cn_Size )
211 /* He have read the file, converts it into PREFS struct */
212 memset(prefs, 0, sizeof(*prefs));
213 prefs->wordssep = WordsSep;
214 prefs->attrtxt.ta_Name = FontName;
215 prefs->attrscr.ta_Name = FontName+30;
216 while(ByteRead < cn->cn_Size)
218 register STRPTR src;
219 src = buffer + ByteRead;
220 if(src[0] < MAX_NUMFIELD) {
221 register STRPTR dest = (STRPTR)prefs+offsets[*src];
222 if(sizefields[ *src ] == 0) dest = *(STRPTR *)dest;
223 CopyMem(src+2, dest, src[1]);
225 ByteRead += src[1]+2;
227 } else err = RETURN_FAIL;
228 if(buffer != NULL) FreeVec( buffer );
229 } else err = RETURN_FAIL;
230 } else err = RETURN_FAIL;
231 close_prefs(file);
232 } else err = RETURN_FAIL;
234 if(err == RETURN_OK)
236 int lock = LockIBase(0);
237 info_screen(prefs, IntuitionBase->ActiveScreen);
238 UnlockIBase(lock);
240 /* If user wants to use a custom font for its interface, try lo **
241 ** load it, otherwise use default screen font of parent screen: */
242 if(!prefs->use_scrfont ||
243 !(prefs->scrfont = (void *) OpenDiskFont( &prefs->attrscr )) )
244 prefs->scrfont = prefs->parent->RastPort.Font;
245 /* Ditto with text font */
246 if(!prefs->use_txtfont ||
247 !(prefs->txtfont = (void *) OpenDiskFont( &prefs->attrtxt )) )
248 prefs->txtfont = GfxBase->DefaultFont;
249 /* Makes valid pointers */
250 text_to_attr(prefs->scrfont, &prefs->attrscr);
251 text_to_attr(prefs->txtfont, &prefs->attrtxt);
252 /* Special characters that separate words */
253 unpack_separators(prefs->wordssep);
255 else
257 int lock = LockIBase(0);
258 set_default_prefs(prefs, IntuitionBase->ActiveScreen);
259 UnlockIBase(lock);
261 /* All done */
262 return err;
265 /*** Save a file where we found it, otherwise in ENVARC: ***/
266 UBYTE save_prefs(PREFS *prefs)
268 APTR file;
269 UBYTE num, size;
270 UBYTE NumField[2];
271 if( (file = open_prefs(Path, MODE_SAVE)) )
273 if( !PushChunk(file, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN) )
275 if( !PushChunk(file, ID_PREF, ID_JANO, IFFSIZE_UNKNOWN) )
277 if (Wnd)
279 /* Save window dimension */
280 CopyMem(&Wnd->LeftEdge, &prefs->left, 4*sizeof(WORD));
282 else
284 int lock;
285 prefs->left = 0;
286 prefs->width = prefs->txtfont->tf_XSize * 80;
288 lock = LockIBase(0);
289 prefs->top = IntuitionBase->ActiveScreen->BarHeight + 1;
290 prefs->height = IntuitionBase->ActiveScreen->Height - prefs->top;
291 UnlockIBase(lock);
294 /* Write configuration file */
295 for(num=0; num < MAX_NUMFIELD; num++) {
296 register STRPTR src;
297 size = sizefields[ num ];
298 src = (STRPTR)prefs + offsets[ num ];
299 if(size == 0) src = *(STRPTR *)src, size = strlen(src)+1;
301 NumField[0] = num; NumField[1] = size;
302 if( WriteChunkBytes(file, NumField, 2) != 2 ||
303 WriteChunkBytes(file, src, size) != size ) break;
305 PopChunk( file );
307 PopChunk( file );
309 close_prefs(file);
311 return 0;
314 /*** Ask for a new font, fixed or not ***/
315 struct TextFont *change_fonts(struct TextAttr *buf, void *Wnd, BOOL fixed)
317 struct FontRequester *fr;
318 struct TextFont *newfont = NULL;
320 if((fr = (void *) AllocAslRequestTags(ASL_FontRequest,
321 ASLFO_FixedWidthOnly, fixed,
322 ASLFO_SleepWindow, TRUE,
323 ASLFO_InitialName, (IPTR)buf->ta_Name,
324 ASLFO_InitialSize, buf->ta_YSize,
325 ASLFO_Window, (IPTR)Wnd,
326 TAG_DONE)))
328 if( AslRequest(fr, NULL) )
330 /* User may hit cancel! */
331 newfont = (void *) OpenDiskFont( &fr->fo_Attr );
333 if( newfont )
335 CopyMem(&fr->fo_Attr, buf, sizeof(*buf));
336 /* The ta_Name field will be freed with FreeAslRequest call ! */
337 buf->ta_Name = newfont->tf_Message.mn_Node.ln_Name;
339 else
340 ThrowError(Wnd, ErrMsg(ERR_LOADFONT));
342 FreeAslRequest(fr);
343 /* Window will be reinitiated later... */
345 return newfont;
348 /*** Ask for new screen information ***/
349 #ifndef JANOPREF
350 ULONG change_screen_mode(UBYTE *Depth, ULONG ModeID)
351 #else
352 /*** JanoPrefs wants some additionnal information ***/
353 ULONG change_screen_mode(WORD *whd, ULONG ModeID)
354 #endif
356 struct ScreenModeRequester *smr;
358 if((smr = (void *) AllocAslRequestTags(ASL_ScreenModeRequest,
359 ASLSM_DoWidth, FALSE,
360 ASLSM_DoHeight, FALSE,
361 ASLSM_DoAutoScroll, FALSE,
362 ASLSM_DoOverscanType, FALSE,
363 ASLSM_DoDepth, TRUE,
364 ASLSM_InitialDisplayID, ModeID,
365 ASLFR_Screen, (IPTR)Scr,
366 TAG_DONE) ))
368 if( AslRequest(smr,NULL) )
370 /* Extract some interresting information about screen */
371 #ifndef JANOPREF
372 *Depth = smr->sm_DisplayDepth;
373 #else
374 whd[0] = smr->sm_DisplayWidth;
375 whd[1] = smr->sm_DisplayHeight;
376 whd[2] = smr->sm_DisplayDepth;
377 #endif
378 ModeID = smr->sm_DisplayID;
379 } else ModeID = INVALID_ID;
380 FreeAslRequest(smr);
381 return ModeID;
383 return INVALID_ID;
386 #ifndef JANOPREF /** Following functions are used only by the editor **/
387 #include "DiskIO.h"
389 /*** Ask where to load/save a preferences file ***/
390 void ask_prefs(Project edit, char save, CONST_STRPTR title )
392 STRPTR new;
393 AskArgs arg;
395 arg.file = (STRPTR) FilePart( arg.dir = Path );
397 if((new = (STRPTR) (save ? ask_save(Wnd, &arg, title) : ask_load(Wnd, &arg, TRUE, title))))
399 CopyMemQuick(new, Path, sizeof(Path));
400 FreeVec(new);
401 if(save) save_prefs(&prefs);
402 else if( load_prefs(&tmpprefs, Path) != RETURN_OK )
403 ThrowError(Wnd, ErrMsg(ERR_BADPREFSFILE));
404 else update_prefs(edit);
408 /*** Ask user for a new font (shortcut of gui) ***/
409 void ask_new_font( void )
411 struct TextFont *newfont;
413 if((newfont = change_fonts(&prefs.attrtxt, Wnd, TRUE)))
415 if( prefs.txtfont ) CloseFont(prefs.txtfont);
416 prefs.use_txtfont = TRUE;
417 prefs.txtfont = newfont;
418 /* Redraw interface */
419 SetFont(RP, prefs.txtfont);
420 new_size(EDIT_AREA);
424 /*** Change screenmode (shortcut of gui) ***/
425 void ask_new_screen( void )
427 ULONG ModeID;
428 if((ModeID = change_screen_mode(&prefs.depth, prefs.modeid)) != INVALID_ID )
430 prefs.modeid = ModeID;
431 prefs.use_pub = TRUE;
432 /* Close everything */
433 CloseMainWnd(1);
434 if( setup() ) cleanup(ErrMsg(ERR_NOGUI), RETURN_FAIL);
435 new_size(EDIT_ALL);
439 /*** Close the pref window, making or not changes effective ***/
440 void update_prefs( Project edit )
442 /* Let's change the settings: */
443 UBYTE flags = 0, col = 0, i;
444 /* We are going to take in account changes wanted by the user. **
445 ** This can imply some deep changes in the interface, try to **
446 ** limit them as possible (i.e:closing screen or window). */
448 /* First, be sure that "parent" screen already exists */
449 if(prefs.use_pub == 0)
451 register struct Screen *list, *first;
452 int lock = LockIBase(0);
454 for(first = list = IntuitionBase->ActiveScreen; list && list != first; list=list->NextScreen)
455 if(list == tmpprefs.parent) {
456 first = NULL; break;
458 UnlockIBase(lock);
460 /** The screen hasn't been found! **/
461 if(first && NULL != (list = (void *) LockPubScreen(NULL)))
462 UnlockPubScreen(NULL, list);
464 tmpprefs.parent = list;
467 /* Want to change the screen where the window is ? */
468 if(prefs.use_pub != tmpprefs.use_pub ||
469 (tmpprefs.use_pub==1 && tmpprefs.modeid!=prefs.modeid) ||
470 (prefs.scrfont != tmpprefs.scrfont && prefs.use_pub))
471 /* Close everything in this case */
472 CloseMainWnd(1), flags = EDIT_ALL;
473 else if(prefs.backdrop != tmpprefs.backdrop)
474 /* Otherwise just the window */
475 CloseMainWnd(0), flags = EDIT_ALL;
476 else
477 /* User has changed the screen font, but the window re- **
478 ** mains on a pubscreen. Therefore, it can't be closed, **
479 ** but change the font that our interface uses anyway: */
480 if(prefs.scrfont != tmpprefs.scrfont)
481 /* Just compute new menu size */
482 flags = EDIT_GUI;
484 /* Look for color changes */
485 for(i=0; i<sizeof(Modif); i++)
486 if( (&prefs.pen.bg)[i] != (&tmpprefs.pen.bg)[i] ) col |= Modif[i];
488 /* Text font has changed, no shutting required */
489 if( prefs.txtfont != tmpprefs.txtfont ) flags |= EDIT_AREA;
491 /* Tabstop changed, need to recompute precomputed tab */
492 if(edit->tabsize != tmpprefs.tabsize)
493 init_tabstop(tmpprefs.tabsize), flags |= EDIT_AREA,
494 edit->tabsize = tmpprefs.tabsize;
496 /* Makes changes effective */
497 CopyMem(&tmpprefs, &prefs, sizeof(prefs));
498 unpack_separators((STRPTR)strcpy(prefs.wordssep = WordsSep, tmpprefs.wordssep));
500 /* Requires to setup the main gui? */
501 if(flags & EDIT_GUI)
503 if( setup() ) cleanup(ErrMsg(ERR_NOGUI), RETURN_FAIL);
504 else new_size(flags | col);
505 } else {
506 /* Pens number has changed? */
507 if( col ) load_pens();
508 /* It isn't required to "reboot" the programme! */
509 SetFont(RP, prefs.txtfont);
510 new_size(flags | col);
514 /*** Find and launch JanoEditor preference tool ***/
515 void setup_winpref( void )
517 static UBYTE JPPath[] = SYS_DIR PREF_DIR PREF_NAME " >NIL:";
518 static IPTR systags[] = {
519 SYS_Input, (IPTR) NULL,
520 SYS_Output, (IPTR) NULL,
521 SYS_Asynch, TRUE,
522 TAG_DONE
524 struct FileLock *lock;
525 UBYTE *path;
527 /* The pref may be already running */
528 if( !send_pref(&prefs, CMD_SHOW) )
530 JPPath[ sizeof(SYS_DIR PREF_DIR PREF_NAME)-1 ] = 0;
531 /* Search the preference editor */
532 if( !(lock = (void *) Lock(path = JPPath, SHARED_LOCK)) )
533 /* But maybe it is in the path */
534 path = JPPath+sizeof(SYS_DIR PREF_DIR)-1;
536 if(lock) UnLock((BPTR)lock);
537 JPPath[ sizeof(SYS_DIR PREF_DIR PREF_NAME)-1 ] = ' ';
539 /* Let's spawn the new process, the pref will be clever enough to **
540 ** ask Jano for it's internal preference it is currently using. */
541 if(SystemTagList(path, (struct TagItem *)systags) != 0)
542 ThrowError(Wnd, ErrMsg(ERR_NOPREFEDITOR));
545 #endif